angualar.js指令与控制器间的通信(@、=、&)以及在指令内部使用$watch监听参数变化
来源:互联网 发布:windows系统截屏快捷键 编辑:程序博客网 时间:2024/05/16 00:34
指令中怎么创建 scope:
scope默认值是false,表示scope跟父controller的scope相同
scope:true,表示创建一个继承自父scope的新scope,这样就可以让同一个父控制下的指令都可以使用这个scope进行通信。
创建完全独立的属于指令自己的scope,这样可以防止读取和修改父级scope的数据。
创建完全独立的scope的API:
=:提供一个与父scope的双向绑定的属性。
&:能够在指令内访问定义在父scope注册的函数。
@:提供一个 父scope-》子指令的单向绑定的属性。
关键是有几点是要理解的:
$scopes上的对象是与html上指令标签的数据模型绑定的,即父控制器上$scope的对象不能直接传给子指令的link函数,被子指令的$scope引用。
数据的流向应该是:
父控制器上$scope的对象绑定html上指令标签的数据模型,该数据模型作为子指令的属性值,然后传给子指令的scope与之绑定。
其它要注意的还有:
html上指令标签的属性名不能有大写。如果指令上的scope的属性值有大写,则对应html上指令标签的属性名必须有-符号。
例如:
指令上的scope的属性名可以与html上指令标签的属性名相一致,这时可以不用写scope的属性值
如果是使用单向数据绑定@,html上指令标签的属性值要加上双花括号{{}}
如果是使用双向数据绑定=,则不用加。
隔离作用域下,父控制器$scope上的变量必须作为指令的属性值
当在指令内部使用$scope.$watch,用以监听父控制器$scope上的对象的值变化时,必须要注意:
1、该值必须用双向绑定;
2、只能以监听指令上的属性值的形式,而不能以监听$scope上的变量的形式。即用“attrs.变量名”
否则不会触发监听
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.name23 }24 }25 }26 });27 </script>28 </body>
- angualar.js指令与控制器间的通信(@、=、&)以及在指令内部使用$watch监听参数变化
- 指令与控制器间的通信详解
- angualar创建自定义指令处理数据变化
- Angular.js中使用$watch监听模型变化
- Angular.js中使用$watch监听模型变化
- Angular.js中使用$watch监听模型变化
- Angular.js中使用$watch监听模型变化
- Angular.js中使用$watch监听模型变化
- Angular.js中使用$watch监听模型变化
- Angular.js中使用$watch监听模型变化 (转载)
- 基于vue-cli的vue项目之vuex的使用5------watch监听vuex内部数据变化
- $watch监听多个值的变化
- Angular中使用$watch监听object属性值的变化
- 使用watch监听路由变化和watch监听对象
- 指令与控制器之间的交互
- ANGULAR JS WATCH监听使用
- 指令与控制器交互,指令与指令交互
- iOS: 使用KVO监听控制器中数组的变化
- mac配置ssh免密码登录centos7
- 泛读---数据结构导论
- win10 无法拨号上网720错误
- cartographer源码分析(55)-mapping-collated_trajectory_builder.h
- C语言二叉树程序
- angualar.js指令与控制器间的通信(@、=、&)以及在指令内部使用$watch监听参数变化
- C语言之基本数据类型(笔记二)
- socket编程中write、read和send、recv之间的区别
- Glide加载相同URL时由于缓存无法更新图片的问题
- WebGL之旅(十六) 层级模型
- 杭电acm 5510Bazinga(字符串)
- ARM平台
- 如何用ARKit将太阳系装进iPhone(二)
- HashMap的数据结构分析