详解angularJs中自定义directive的数据交互


Posted in Javascript onJanuary 13, 2017

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

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

<body ng-app="myApp" ng-controller="myCtrl">
<test-directive></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
        $scope.data = {
          name:"白衣如花"
        };
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          template:"<h1>{{data.name||'未定义'}}</h1>"
        }
      });
</script>
</body>

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

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

<body ng-app="myApp" ng-controller="myCtrl">
<test-directive></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
        $scope.data = {
          name:"白衣如花"
        };
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {},
          template:"<h1>{{data.name||'未定义'}}</h1>"
        }
      });
</script>
</body>

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

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

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

<body ng-app="myApp" ng-controller="myCtrl">
<p>名字:{{outerName}}</p>
<test-directive inner-name="outerName"></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {
            innerName: "="
          },
          template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>"
        }
      });
</script>
</body>

显示结果如下:

详解angularJs中自定义directive的数据交互

分析:从数据流向说起,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内部意外修改数据该怎么办呢?于是单向绑定"@"就出场了。

<body ng-app="myApp" ng-controller="myCtrl">
<input type='text' ng-model='outerName' placeholder='白衣如花'>
<test-directive inner-name="{{outerName}}"></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {
            innerName: "@"
          },
          template:"<p>名字:{{innerName}}</p>" +
          "<button ng-click='innerName=innerName+1'>点击</button>"
        }
      });
</script>
</body>

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

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

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

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

<body ng-app="myApp" ng-controller="myCtrl">
<p>名字:{{outerName}}</p>
<test-directive on-click="click(name)"></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
        $scope.click = function (name) {
          $scope.outerName = name || "白衣如花";
        }
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {
            onClick: "&"
          },
          template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>" +
          "<button ng-click='onClick({name: innerName})'>点击</button>"
        }
      });
</script>
</body>

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

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

<body ng-app="myApp" ng-controller="myCtrl">
<button ng-click="click()">重置</button>
<test-directive action="action"></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
        $scope.action = {};
        $scope.click = function () {
          $scope.action.reset();
        }
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {
            action: "="
          },
          template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
          controller: function ($scope) {
            $scope.action.reset = function () {
              $scope.name = "白衣如花"
            }
          }
        }
      });
</script>
</body>

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

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

<body ng-app="myApp" ng-controller="myCtrl">
<test-directive action="action"></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
        $scope.action = {};
        $scope.action.init();
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {
            action: "="
          },
          template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
          controller: function ($scope) {
            $scope.action.init = function () {
              $scope.name = "白衣如花"
            }
          }
        }
      });
</script>
</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。代码如下:

<body ng-app="myApp" ng-controller="myCtrl">
<test-directive action="action"></test-directive>
<script>
  angular.module("myApp",[])
      .controller("myCtrl",function($scope){
        $scope.action = {name: "白衣如花"};
      })
      .directive("testDirective",function(){
        return {
          restrict:"E",
          scope: {
            action: "="
          },
          template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
          link: function (scope, elem, attrs) {
            scope.$watch(attrs.action, function (value) {
              scope.action.init();
            })
          },
          controller: function ($scope) {
            $scope.action.init = function () {
              $scope.name = $scope.action.name
            }
          }
        }
      });
</script>
</body>

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
Aug 15 Javascript
Js判断参数(String,Array,Object)是否为undefined或者值为空
Nov 04 Javascript
jqGrid增加时--判断开始日期与结束日期(实例解析)
Nov 08 Javascript
Jquery遍历Json数据的方法
Apr 20 Javascript
jQuery寻找n以内完全数的方法
Jun 24 Javascript
基于javascript实现单选及多选的向右和向左移动实例
Jul 25 Javascript
jQuery插件zTree实现删除树子节点的方法示例
Mar 08 Javascript
详解vue项目优化之按需加载组件-使用webpack require.ensure
Jun 13 Javascript
五步轻松实现JavaScript HTML时钟效果
Mar 25 Javascript
vue项目中将element-ui table表格写成组件的实现代码
Jun 12 Javascript
v-slot和slot、slot-scope之间相互替换实例
Sep 04 Javascript
JavaScript阻止事件冒泡的方法
Dec 06 Javascript
微信小程序 MD5加密登录密码详解及实例代码
Jan 12 #Javascript
很棒的一组js图片轮播特效
Jan 12 #Javascript
微信小程序 页面跳转传递值几种方法详解
Jan 12 #Javascript
微信小程序 详解Page中data数据操作和函数调用
Jan 12 #Javascript
百度地图API之百度地图退拽标记点获取经纬度的实现代码
Jan 12 #Javascript
js实现微博发布小功能
Jan 12 #Javascript
基于jQuery实现照片墙自动播放特效
Jan 12 #Javascript
You might like
PHP操作Memcache实例介绍
2013/06/14 PHP
php计算年龄精准到年月日
2015/11/17 PHP
ModelDialog JavaScript模态对话框类代码
2011/04/17 Javascript
Jquery加载时从后台读取数据绑定到dropdownList实例
2013/06/09 Javascript
window.onload和$(function(){})的区别介绍
2013/10/30 Javascript
点击弹出层效果&amp;弹出窗口后网页背景变暗效果的实现代码
2014/02/10 Javascript
JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
2014/08/16 Javascript
jquery判断复选框是否选中进行答题提示特效
2015/12/10 Javascript
JavaScript电子时钟倒计时第二款
2016/01/10 Javascript
利用node.js搭建简单web服务器的方法教程
2017/02/20 Javascript
angular学习之ngRoute路由机制
2017/04/12 Javascript
Vue+axios 实现http拦截及路由拦截实例
2017/04/25 Javascript
mui框架移动开发初体验详解
2017/10/11 Javascript
150行代码带你实现微信小程序中的数据侦听
2019/05/17 Javascript
Vue中util的工具函数实例详解
2019/07/08 Javascript
[02:40]DOTA2英雄基础教程 巨牙海民
2013/12/23 DOTA
python 文件操作api(文件操作函数)
2016/08/28 Python
Python读取txt内容写入xls格式excel中的方法
2018/10/11 Python
使用Python的SymPy库解决数学运算问题的方法
2019/03/27 Python
python读取tif图片时保留其16bit的编码格式实例
2020/01/13 Python
python scatter函数用法实例详解
2020/02/11 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
谈谈Python:为什么类中的私有属性可以在外部赋值并访问
2020/03/05 Python
Java Unsafe类实现原理及测试代码
2020/09/15 Python
Python函数调用追踪实现代码
2020/11/27 Python
canvas压缩图片以及卡片制作的方法示例
2018/12/04 HTML / CSS
英国领先的汽车轮胎和快速健康中心:Kwik Fit
2017/10/29 全球购物
The North Face北面英国官网:美国著名户外品牌
2017/12/13 全球购物
阿玛瑞酒店中文官方网站:Amari.com
2018/02/13 全球购物
自荐信不宜过于夸大
2013/11/06 职场文书
安全生产检查通报
2014/01/29 职场文书
2014年教师节活动总结
2014/08/29 职场文书
2014镇副书记群众路线专题民主生活会思想汇报
2014/09/23 职场文书
向国旗敬礼活动总结
2014/09/27 职场文书
网络妈妈观后感
2015/06/08 职场文书
用Python制作灯光秀短视频的思路详解
2021/04/13 Python