我认为限制指令的范围意味着controller。scope和directive.scope不再是同一个东西。然而,我困惑的是如何将模型放置在指令模板内或在html中影响数据绑定。我觉得我错过了一些非常根本的东西,继续前进,我需要理解这一点。
拿下面的代码(这里调用:http://jsfiddle.net/2ams6/)
JavaScript
var app = angular.module('app',[]); app.controller('Ctrl',function($scope){ }); app.directive('testel',function(){ return { restrict: 'E',scope: { title: '@' },transclude: true,template: '<div ng-transclude>'+ '<h3>Template title: {{title}}</h3>' + '<h3>Template data.title:{{data.title}}</h3>' + '</div>' } });
HTML
<div ng-app='app'> <div ng-controller="Ctrl"> <input ng-model="data.title"> <testel title="{{data.title}}"> <h3>Transclude title:{{title}}</span></h3> <h3>Transclude data.title:{{data.title}}</h3> </testel> </div> </div>
模型仅更新模板中的{{title}},并更新互换中的{{data.title}}。为什么模板中的{{title}}不是{{data.title}}?
将输入移动到这样的转换中(这里:http://jsfiddle.net/eV8q8/1/):
<div ng-controller="Ctrl"> <testel title="{{data.title}}"> <input ng-model="data.title"> <h3>Transclude title: <span style="color:red">{{title}}</span></h3> <h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3> </testel> </div>
现在意味着只有transclude {{data:title}}得到更新。为什么不使用模板{{title}}或{{data.title}},也不转换{{title}}?
最后,将输入移动到模板中,如下所示(fiddle here:http://jsfiddle.net/4ngmf/2/):
template: '<div ng-transclude>' + '<input ng-model="data.title" />' + '<h3>Template title: {{title}}</h3>' + '<h3>Template data.title: {{data.title}}</h3>' + '</div>'
现在意味着只有模板{{data.title}}得到更新。再次,为什么不是其他3绑定?
我希望有一些明显的盯着我在脸上,我错过了。如果你让我得到这个,我会给你买啤酒,或给你一些点,或一些其他这样的事情。非常感谢。
>与控制器Ctrl相关联的范围,因为ng-controller
>一个指令的transcluded作用域,因为transclude:true
> a指令隔离范围,因为范围:{…}
在fiddle1中,在我们在文本框中输入任何内容之前,我们有以下:
范围003是与控制器关联的范围。因为我们没有键入到文本框中,所以没有数据属性。在隔离范围004中,我们看到创建了一个title属性,但它是空的。它为空,因为父作用域还没有data.title属性。
在文本框中输入我的标题后,我们现在有:
控制器范围003现在有一个新的数据对象属性(这是为什么它是黄色的),它有一个title属性现在设置为我的标题。因为隔离范围属性标题是单向数据绑定到data.title的内插值,它也获得值my标题(该值是黄色,因为它改变)。
被转换的范围原型上继承于控制器范围,因此在转换的HTML中,angular可以遵循原型链,并在父范围中找到$ scope.data.title(但$ scope.title不存在)。
在fiddle2中,在输入之前我们有和fiddle1一样的图片。
输入我的标题后:
注意新的data.title属性显示在转录作用域上的位置。隔离范围仍然在控制器范围上寻找data.title,但是它在这里没有,所以它的title属性值保持为空。
在fiddle3中,在打字之前我们有和fiddle1一样的图片。
输入我的标题后:
注意新的data.title属性显示在隔离范围上的位置。其他任何作用域都无法访问隔离作用域,因此字符串my title不会出现在其他位置。
更新Angular v1.2:
With change eed299a Angular现在在转义之前清除了转义点,因此Template title:…和Template data.title:…部分不会显示,除非您修改模板,以使ng-transclude本身,例如如:
'<h3>Template title: <span style="color:red">{{title}}</span></h3>' + '<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>' + '<div ng-transclude></div>'
在下面的更新Angular v1.3,这个模板更改。
Angular v1.3的更新:
从Angular v1.3开始,被转换的作用域现在是指令的孤立作用域的子元素,而不是控制器作用域的子元素。所以在fiddle1,在我们输入任何东西之前:
本更新中的图片是用Peri$scope工具绘制的,因此图片有点不同。 @表示我们有一个使用@语法的隔离范围属性,粉红色的背景意味着该工具无法为映射找到一个祖先引用(这是真的,因为我们没有在文本框中输入任何内容)。
在文本框中输入我的标题后,我们现在有:
使用@ binding的隔离属性将始终在@符号后的隔离范围中显示插值字符串结果。 Peri $ scope也能够在祖先范围中找到此精确的字符串值,因此它也显示对该属性的引用。
在小提琴2,在打字之前我们有和fiddle1一样的图片。
输入我的标题后:
注意新的data.title属性显示在转录作用域上的位置。隔离范围仍然在控制器范围上寻找data.title,但是它在这里没有,所以它的title属性值保持为空。
在fiddle3中,在打字之前我们有和fiddle1一样的图片。
输入我的标题后:
注意新的data.title属性显示在隔离范围上的位置。即使转录作用域通过$ parent关系访问了孤立作用域,它也不会查找title或data.title – 它只会查找控制器作用域(即它将遵循原型继承)并且控制器作用域没有定义这些属性。