zoukankan      html  css  js  c++  java
  • angularJs中自定义directive的数据交互

    首先放官方文档地址:https://docs.angularjs.org/guide/directive

      就我对directive的粗浅理解,它一般用于独立Dom元素的封装,应用场合为控件重用和逻辑模块分离。后者我暂时没接触,但数据交互部分却是一样的。所以举几个前者的例子,以备以后忘记。

      directive本身的作用域$scope可以选择是否封闭,不封闭则和其controller共用一个作用域$scope。例子如下:

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <test-directive></test-directive>
     3 <script>
     4     angular.module("myApp",[])
     5             .controller("myCtrl",function($scope){
     6                 $scope.data = {
     7                     name:"白衣如花"
     8                 };
     9             })
    10             .directive("testDirective",function(){
    11                 return {
    12                     restrict:"E",
    13                     template:"<h1>{{data.name||'未定义'}}</h1>"
    14                 }
    15             });
    16 </script>
    17 </body>

      显示结果为:白衣如花,可以知道directive中的data.name就是myCtrl控制器中的$scope.data.name。

      那么封闭的directive呢?怎么封闭,封闭效果是什么样的,封闭后怎么数据交互?这些都是我这几天摸索的东西。

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <test-directive></test-directive>
     3 <script>
     4     angular.module("myApp",[])
     5             .controller("myCtrl",function($scope){
     6                 $scope.data = {
     7                     name:"白衣如花"
     8                 };
     9             })
    10             .directive("testDirective",function(){
    11                 return {
    12                     restrict:"E",
    13                     scope: {},
    14                     template:"<h1>{{data.name||'未定义'}}</h1>"
    15                 }
    16             });
    17 </script>
    18 </body>

    结果显示为:未定义。所以在directive定义时,添加属性scope就可以把directive的作用域和父控制器的作用域分离开来。

    好,了解了开放和封闭之后,进入主题,如何进行数据交互。个人觉得数据交互分为:父控制器获取directive的变量;directive获取父控制器的变量;父控制器调用directive的函数;directive调用父控制器的函数。

    1.父控制器获取directive的变量。比如封装了一个输入框接受用户输入,父控制器点击搜索按钮要获取用户输入:

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <p>名字:{{outerName}}</p>
     3 <test-directive inner-name="outerName"></test-directive>
     4 <script>
     5     angular.module("myApp",[])
     6             .controller("myCtrl",function($scope){
     7             })
     8             .directive("testDirective",function(){
     9                 return {
    10                     restrict:"E",
    11                     scope: {
    12                         innerName: "="
    13                     },
    14                     template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>"
    15                 }
    16             });
    17 </script>
    18 </body>

    显示结果如下:

    分析:从数据流向说起,testDirective中的一个input输入绑定在innerName中,innerName是directive私有作用域拥有的变量,外部控制器不能直接用。通过innerName: "="传递给html中的inner-name属性,

    而inner-name属性则绑定在外部控制器的outerName变量中,所以最后显示在最上面的<p>标签内。上述代码等价于如下代码:

    <test-directive name="outerName"></test-directive>
    scope: {
        innerName: "=name"
    },

     由inerName: "="变成了innerName: "=name",而html属性绑定也由inner-name变成了name。

    2.directive获取父控制器的变量。这个应用场合应该挺多的,比如公共的页眉页脚,公共的展示面板等。

    这个用上面例子的"="一样可以实现,于是我们知道了"="是双向绑定。但是我们要防止directive内部意外修改数据该怎么办呢?于是单向绑定"@"就出场了。

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <input type='text' ng-model='outerName' placeholder='白衣如花'>
     3 <test-directive inner-name="{{outerName}}"></test-directive>
     4 <script>
     5     angular.module("myApp",[])
     6             .controller("myCtrl",function($scope){
     7             })
     8             .directive("testDirective",function(){
     9                 return {
    10                     restrict:"E",
    11                     scope: {
    12                         innerName: "@"
    13                     },
    14                     template:"<p>名字:{{innerName}}</p>" +
    15                     "<button ng-click='innerName=innerName+1'>点击</button>"
    16                 }
    17             });
    18 </script>
    19 </body>

    值得注意的是:@在html的属性绑定时需要{{}}开标识,而=则不用。我的理解是,对于父控制器而言,@是数据传递,而=是数据绑定,所以有这些区别。directive中加入了一个按钮用于验证修改数据后

    父控制器是否发生改变,结果是=有变化,@无变化,很容易得出结论:=是双向绑定,@是单向绑定。

    3.directive调用父控制器的函数。应用场合,暂时想不到(汗)。

    变量用=和@来传递,函数则用&。例子如下:

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <p>名字:{{outerName}}</p>
     3 <test-directive on-click="click(name)"></test-directive>
     4 <script>
     5     angular.module("myApp",[])
     6             .controller("myCtrl",function($scope){
     7                 $scope.click = function (name) {
     8                     $scope.outerName = name || "白衣如花";
     9                 }
    10             })
    11             .directive("testDirective",function(){
    12                 return {
    13                     restrict:"E",
    14                     scope: {
    15                         onClick: "&"
    16                     },
    17                     template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>" +
    18                     "<button ng-click='onClick({name: innerName})'>点击</button>"
    19                 }
    20             });
    21 </script>
    22 </body>

    数据传递流程和之上的例子差不多,唯一要注意的是参数传递时,{name: innerName}前者是形参,后者是实参。多个参数时,参数顺序不重要,形参一一对应。

    4.父控制器调用directive的函数。这个是前段时间遇到的难点,情况较其他复杂一些。应用场合也很普遍,比如初始化,重置等。

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <button ng-click="click()">重置</button>
     3 <test-directive action="action"></test-directive>
     4 <script>
     5     angular.module("myApp",[])
     6             .controller("myCtrl",function($scope){
     7                 $scope.action = {};
     8                 $scope.click = function () {
     9                     $scope.action.reset();
    10                 }
    11             })
    12             .directive("testDirective",function(){
    13                 return {
    14                     restrict:"E",
    15                     scope: {
    16                         action: "="
    17                     },
    18                     template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
    19                     controller: function ($scope) {
    20                         $scope.action.reset = function () {
    21                             $scope.name = "白衣如花"
    22                         }
    23                     }
    24                 }
    25             });
    26 </script>
    27 </body>

     又一次用到了=,利用了js中函数也是属性的原理。似乎,理解了=的双向绑定,就很容易调用directive内部函数了。但是初始化呢?

    首先想到的是类似的=来引用传递:

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <test-directive action="action"></test-directive>
     3 <script>
     4     angular.module("myApp",[])
     5             .controller("myCtrl",function($scope){
     6                 $scope.action = {};
     7                 $scope.action.init();
     8             })
     9             .directive("testDirective",function(){
    10                 return {
    11                     restrict:"E",
    12                     scope: {
    13                         action: "="
    14                     },
    15                     template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
    16                     controller: function ($scope) {
    17                         $scope.action.init = function () {
    18                             $scope.name = "白衣如花"
    19                         }
    20                     }
    21                 }
    22             });
    23 </script>
    24 </body>

    但是运行却发现,错误显示$scope.action.init is not a function,看提示应该是运行到第7行的时候,$scope.action.init函数还未定义。怎么办呢?把directive提到controller之前试试?一样是错误。

    嗯,可以不用函数,直接在directive的controller中执行$scope.name = "白衣如花",似乎很完美,但如果是有参数的初始化呢?事实上js分离后,我遇到的问题是根据http请求的返回结果来初始化directive,由于

    网络快慢不一定,导致控件初始化时不一定有http请求的返回(没有有效的初始化参数),也不能保证http请求返回后directive已经初始化(不能用=来进行函数调用)。

    需求很明了了,如果能监控参数变化,再执行初始化,此时能保证directive已经加载,而且有有效的参数。正好angularjs提供了$watch。代码如下:

     1 <body ng-app="myApp" ng-controller="myCtrl">
     2 <test-directive action="action"></test-directive>
     3 <script>
     4     angular.module("myApp",[])
     5             .controller("myCtrl",function($scope){
     6                 $scope.action = {name: "白衣如花"};
     7             })
     8             .directive("testDirective",function(){
     9                 return {
    10                     restrict:"E",
    11                     scope: {
    12                         action: "="
    13                     },
    14                     template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
    15                     link: function (scope, elem, attrs) {
    16                         scope.$watch(attrs.action, function (value) {
    17                             scope.action.init();
    18                         })
    19                     },
    20                     controller: function ($scope) {
    21                         $scope.action.init = function () {
    22                             $scope.name = $scope.action.name
    23                         }
    24                     }
    25                 }
    26             });
    27 </script>
    28 </body>

    这是我对于directive数据交互的粗浅理解。想要更详细了解,请参看官方文档:https://docs.angularjs.org/guide/directive

  • 相关阅读:
    phpcms 栏目图片循环调用
    phpcms调栏目图片
    Java 面向对象 --单例模式
    Java 面向对象 --包装类
    Java 面向对象 --匿名内部类
    Java面向对象--instanceof关键字
    Java 面向对象 --Object类
    Java 面向对象 --多态性
    Java 面向对象 --接口
    Java 面向对象 --抽象类
  • 原文地址:https://www.cnblogs.com/blogXy/p/6279290.html
Copyright © 2011-2022 走看看