dew*_*ewd 55 angularjs angularjs-directive angularjs-scope
我正在努力理解模型的范围及其对范围有限的指令的约束.
我认为限制指令的范围意味着控制器.$ 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>'
}
});
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
模型仅{{title}}在模板内和翻译{{data.title}}中更新.为什么不在翻译{{title}}中也不{{data.title}}在模板中?
将输入移动到translude中就像这样(在这里小提琴: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>
Run Code Online (Sandbox Code Playgroud)
现在意味着只有transclude {{data:title}}才会更新.为什么不要么模板{{title}}或{{data.title}},也不transclude {{title}}?
最后,将输入移动到模板中,就像这样(在这里小提琴: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>'
Run Code Online (Sandbox Code Playgroud)
现在意味着只有模板{{data.title}}得到更新.再次,为什么不是其他3个绑定?
我希望有一些明显的东西在我面前盯着我,我想念它.如果你让我得到这个,我会给你买啤酒,或给你一些积分,或其他一些这样的东西.非常感谢.
Mar*_*cok 113
你的小提琴创建了三个范围:
Ctrl,因为ng-controllertransclude: truescope: { ... }在fiddle1中,在我们在文本框中输入任何内容之前,我们有以下内容:

范围003是与控制器相关联的范围.由于我们尚未输入文本框,因此没有data属性.在隔离范围004中,我们看到title已创建属性,但它是空的.它是空的,因为父作用域还没有data.title属性.
输入my title文本框后,我们现在有:

控制器范围003现在有一个新的data对象属性(这就是为什么它被涂成黄色),它的title属性现在设置为my title.由于隔离范围属性title是单向数据绑定到内插值data.title,因此它也获得值my title(该值因为更改而着色为黄色).
转换范围原型继承自控制器范围,因此在转换HTML中,angular可以跟随原型链并$scope.data.title在父范围内查找(但$scope.title在那里不存在).
隔离范围只能访问自己的属性,因此只能访问属性title.
在fiddle2中,在输入之前我们有与fiddle1相同的图片.
输入后my title:

注意新data.title属性出现的位置 - 在转换范围内.隔离范围仍在寻找data.title控制器范围,但这次不存在,因此其title属性值仍为空.
在小提琴3中,在输入之前我们有与fiddle1相同的图片.
输入后my title:

注意新data.title属性出现的位置 - 在隔离范围上.其他任何范围都不能访问隔离范围,因此字符串my title不会出现在其他任何位置.
Angular v1.2的更新:
随着变化eed299a角现在清除transcluding前transclusion点,所以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>'
Run Code Online (Sandbox Code Playgroud)
在下面针对Angular v1.3的更新中,进行了此模板更改.
Angular v1.3 +的更新:
从Angular v1.3开始,transcluded范围现在是指令的隔离范围的子代,而不是控制器范围的子代.所以在fiddle1中,在我们输入任何内容之前:

此更新中的图片是使用Peri $ scope工具绘制的,因此图片有点不同.这@表明我们有一个使用@语法的隔离范围属性,粉红色背景意味着该工具无法找到映射的祖先引用(这是真的,因为我们还没有在文本框中输入任何内容).
输入my title文本框后,我们现在有:

使用@绑定的隔离属性将始终在@符号后面的隔离范围中显示插值字符串结果.Peri $ scope也能够在祖先范围内找到这个确切的字符串值,因此它还显示了对该属性的引用.
在小提琴2中,在打字之前我们有与fiddle1相同的图片.
输入后my title:

注意新data.title属性出现的位置 - 在转换范围内.隔离范围仍在寻找data.title控制器范围,但这次不存在,因此其title属性值仍为空.
在小提琴3中,在输入之前我们有与fiddle1相同的图片.
输入后my title:

注意新data.title属性出现的位置 - 在隔离范围上.即使被转换的范围可以通过$parent关系访问隔离范围,它也不会查找title或者data.title- 它只会查看控制器范围(即,它将遵循原型继承),并且控制器范围不会t定义了这些属性.
dew*_*ewd 22
在阅读了所有提出的答案之后,包括Mark的精彩原理图,这是我对范围的理解,以及它对我的问题的继承.我希望评论这个图表的位置,以便我可以适当更新.我希望它只是对Mark提出的内容提供了不同的看法:

好问,顺便问一下!希望我的回答是雄辩的......
答案与变换元素如何获得其范围有关.
总而言之,您有两个范围:
$scope.data.title.(由您的input元素隐式添加)$scope.title.当您更改控制器时$scope.data.title,指令$scope.title也会更改.
您还有两个HTML部分,即transcluded和模板.发生的事情是,被转换的HTML在控制器的范围内,而模板HTML在指令的范围内.因此,转换的HTML不知道任何内容title,并且模板范围对此一无所知data.title
这实际上就是Transclusion的目的 - 允许指令的子元素保持其父作用域,在这种情况下是控制器的作用域.根据设计,transcluded元素不知道它们在指令中,因此无法访问指令的作用域.
另一方面,指令模板只能访问指令的范围.
我已经改变了你的代码,使名称更清晰(但功能相同)