前言 |
众所周知,我们在自定义指令时,会指定它的作用域,即scope设置项(默认值为false)。
且,scope设置项,可以有三种值,从而也就代表三种不同的作用域,下面我们再来一起回顾下:
指令之scope |
|
scope: false |
默认值,指令不会新建一个作用域,使用父级作用域。 |
scope: true |
指令会创建一个新的子作用域,原型继承于父级作用域。 |
scope: {…} |
指令会新建一个隔离作用域,不会原型继承父作用域。 |
好了,通过上面,我们很容易知道,在一个元素绑定一个指令,那么仅仅看这个指令的scope,就轻易知道了它的作用域。
但是,假如我们在一个元素上绑定多个指令呢?这个元素的作用域该如何表现呢?
这就是该篇博客核心----一个元素上绑定多个指令,元素的作用域何去何从。
下面,我们就一起来研究下吧。
另,在此之前,为了接下来的研究方便,我们先约定下,将指令scope的不同值,称为false指令,true指令以及isolated指令。
且需要注意的是,多个指令绑定在一个元素上时,只能有且仅有一个指令拥有template哦,不然会报错的。
Demo如下:
<!-- 多个指令绑定在一个元素上时,只能有一个template,不然会报错,如下 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> <div directive-one directive-tow></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: false, template:‘<div>one</div>‘ }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, template: ‘<div>another</div>‘ }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码结果为:
多个false指令共存 |
首先,我们一起研究的是多个false指令共存情况。
什么意思呢?
即,在一个元素上绑定多个指令,且这些指令的scope值都为false,scope:false。
好了,我们写个demo看看。
<!-- false指令与false指令共存:表现形式为false 不创建作用域,共享父作用域 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: false, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: false, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
打开chrome控制器,得下:
结论如下:
多个false指令共存时,表现形式如同单个指令的scope:false一样,即多个false指令共享父级作用域。
多个true指令共存 |
何为多个true指令共存?
即,在一个元素上绑定多个指令,且这些指令的scope值都为true,scope:true。
好了,我们写个demo看看。
<!-- true指令与true指令共存:表现形式为true 创建一个子作用域,大家一起共享 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: true, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: true, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
打开chrome控制器,得下:
结论如下:
多个true指令共存时,表现形式如同单个指令的scope:true一样,即多个true指令都共享新创建的子作用域,且子作用域继承自父作用域。
多个isolated指令共存 |
何为多个isolated指令共存?
即,在一个元素上绑定多个指令,且这些指令的scope值都为对象,scope:{…}。
好了,我们一起写个demo看看。
<!-- isolated指令与isolated指令共存:报错 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: {}, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: {}, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
运行代码,报错:
结论如下:
多个isolated指令不能共存,否则报错。
false指令与true指令共存 |
何为false指令与true指令共存呢?
即,在一个元素上绑定多个指令,且这些指令的scope值,要么是false,要么是true。
好了,我们一起写个demo看看。
<!-- false指令与true指令共存:(表现形式如true) 将共享新建的scope,即子作用域,并且该scope原型继承自父scope将共享新建的scope,即子作用域,并且该scope原型继承自父scope --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: false, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: true, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
打开chrome控制器,如下:
结论如下:
false指令与true指令共存时,表现形式如同单个指令的scope:true一样,即这些指令都共享新创建的子作用域,且子作用域继承自父作用域。
false指令与isolated指令共存 |
何为false指令与true指令共存呢?
即,在一个元素上绑定多个指令,且这些指令的scope值,要么是false,要么是对象{…}。
好了,我们一起写个demo看看。
<!-- false指令与isolate指令共存:各管各的 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow name="Monkey"></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: false, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: { name: ‘@‘ }, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
打开chrome控制器,如下:
咦,怎么scope指令不一样呢?
通过上面动态操作图,可知指令的作用域是false的。但是,控制器的结果中却显示两个不同的scope。
那么,是不是与template有关呢?
因为,在一个元素上绑定多个指令,只能有一个指令可以设置template。
上述实验中,我们是在scope为false的指令中设置的template,那么我们再来写个demo,紧紧将scope为false的template内容,移到scope为对象的指令中。
如下:
<!-- false指令与isolate指令共存:各管各的 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow name="Monkey"></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: false, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: { name: ‘@‘ }, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
我靠,果然与template的设置有关呢。
结论如下:
false指令与isolated指令共存时,表现形式与template的设置有关:
1、如果template设置在false指令中,则表现为false指令
2、如果template设置在isolated指令中,则表现为isolated指令,即隔离作用域
注意:上述仅限于通过template呈现在页面中时,在编译链接阶段,他们是各管各的,即isolated指令的作用域是isolated,false指令的作用域是false,因为在上面的chrome控制器的截图,也能看见,它们的scope是不一样的。
true指令与isolated指令共存 |
何为true指令与isolated指令共存呢?
即,在一个元素上绑定多个指令,且这些指令的scope值,要么是true,要么是对象{…}。
好了,我们一起写个demo看看。
<!-- true指令与isolate指令共存:各管各 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-tow directive-one name="Monkey"></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: true, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: { name: ‘@‘ }, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
打开chrome控制器,如下:
是八是,发现了点什么?怎么两个scope又是不一样的。哈哈哈,看来它们又是与template的绑定有关呢。
如下,我将template移动到isolated指令中。
<!-- true指令与isolate指令共存:各管各 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-tow directive-one name="Monkey"></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: true, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: { name: ‘@‘ }, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
So,结论如下:
true指令与isolated指令共存时,表现形式与template的设置有关:
1、如果template设置在true指令中,则表现为true指令
2、如果template设置在isolated指令中,则表现为isolated指令,即隔离作用域
注意:上述仅限于通过template呈现在页面中时,在编译链接阶段,他们是各管各的,即isolated指令的作用域是isolated,true指令的作用域是true,因为在上面的chrome控制器的截图,也能看见,它们的scope是不一样的。
false指令、true指令以及isolated指令三者共存 |
何为三者共存?
即,在一个元素上绑定多个指令,且这些指令的scope值包括了false、true以及{…}。
好了,我们写个demo看看。
<!-- isolated指令与false指令、true指令共存:表现形式如下: 1、假设template绑定在false或者true指令上,表现为true 2、假设template绑定在isolated上,表现为isolated,前提是只有一个isolated,不然多个isolated会报错 --> <!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app="myApp"> pare:<input type="text" ng-model="name"/> <div directive-one directive-tow directive-three></div> <script> var app = angular.module(‘myApp‘, []); app.directive(‘directiveOne‘, function(){ return { restrict: ‘A‘, scope: true, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveTow‘, function(){ return { restrict: ‘A‘, scope: false, link: function(scope){ console.log(scope); } }; }); app.directive(‘directiveThree‘, function(){ return { restrict: ‘A‘, scope: {}, template:‘dire:<input type="text" ng-model="name"/>‘, link: function(scope){ console.log(scope); } }; }); </script> </body> </html>
代码稍长,请自行打开
执行上述代码,结果如下:
打开chrome控制器,如下:
可以看见false指令和true指令时,它们都共享同一个作用域,而isolated指令单独一个作用域。
且,上述代码中,我们将template绑定到isolated指令中的,故而表现结果为isolated。
假设,我们将template绑定到false指令或者true指令中呢?
答案,就是如同false指令与true指令共存的情况(PS:这里就不demo啦,不信,就自己动手试试)。
另外,还需要注意的是,isolated指令只能为一个,不然会报错哦,我们在 "isolated指令与isolated指令" 中,已经探讨过啦。
So,结论如下:
当false指令、true指令以及isolated指令共存时,表现形式与template的设置有关:
1、假设template绑定在true或者false指令中,表现如同“false指令与true指令共存”情况;
2、假设template绑定在isolated指令中,表现为scope:{…}
注意:上述仅限于通过template呈现在页面中时,在编译链接阶段,他们是各管各的,即isolated指令的作用域是isolated,true指令和false指令来那个的作用域为新建子作用域且共享这个新作用域。
外絮--transclude |
当指令中设置了transclude:true,ng-transclude中作用域又会是怎么回事呢?
对于transclude,只需记住:利用ng-transclude嵌入的内容的同时,会创建一个属于自己的作用域,即子作用域,且继承自外部作用域,并非指令。