混淆了Angularjs跨越和隔离范围和绑定
我很难理解范围有限的指令范围及其约束力。
我得到的限制在一个指令的范围意味着控制器。$ 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}} ?
将input移动到像这样的跨越(在这里摆弄: 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}} ,也不是{{data.title}} {{title}} ?
最后,将input移动到模板内,像这样(在这里提琴: 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个绑定?
我希望有一些明显的盯着我,我很想念它。 如果你让我得到这个,我会给你买一瓶啤酒,或者给你一些点数,或者其他的一些东西。 非常感谢。
你的小提琴创造了三个范围:
- 由于
ng-controller,与控制器Ctrl相关的范围 - 一个指令transcluded作用域,因为
transclude: true - 一个指令隔离范围,由于
scope: { ... }
在小提琴1中,在我们input任何文字之前,我们有以下几点:

范围003是与控制器相关的范围。 由于我们尚未input文本框,因此没有data属性。 在隔离范围004中,我们看到创build了一个title属性,但是它是空的。 它是空的,因为父范围还没有data.title属性。
在文本框中inputmy title后,我们现在有:

控制器作用域003现在有一个新的data对象属性(这就是为什么它是黄色的),它的title属性现在设置为my title 。 由于隔离作用域属性title是单向数据绑定到data.title的插值,所以它也得到my title的值(因为它已经改变,所以这个值是黄色的)。
transcluded作用域原型从控制器作用域inheritance,因此在$scope.data.title HTML中,angular可以遵循原型链,并在父作用域中find$scope.data.title (但$scope.title在那里不存在)。
隔离范围只能访问自己的属性,因此只有属性title 。
在fiddle2中,在打字前我们有和fiddle1一样的图片。
inputmy title :

注意新的data.title属性出现在data.title作用域上。 隔离作用域仍然在控制器作用域上查找data.title ,但是这次没有,所以它的title属性值保持为空。
在小提琴3中,在打字之前,我们有和fiddle1一样的照片。
inputmy title :

注意新的data.title属性出现在隔离范围内。 其他范围都没有访问隔离范围,所以stringmy title不会出现在其他地方。
更新Angular v1.2:
随着改变eed299a Angular现在清除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>'
在下面的Angular v1.3更新中,进行了这个模板更改。
更新Angular v1.3 +:
由于Angular v1.3,transcluded作用域现在是该指令的隔离作用域的子项,而不是控制器作用域的子项。 所以在小提琴1中,在我们input任何东西之前:

这个更新中的图片是用Peri $ scope工具绘制的,所以图片有点不一样。 @表示我们有一个使用@语法的隔离作用域属性,粉红色的背景表示该工具无法find映射的祖先引用(这是真的,因为我们没有input任何东西到文本框)。
在文本框中inputmy title后,我们现在有:

使用@绑定的隔离属性将始终在@符号之后的隔离范围中显示插入的string结果。 Peri $ scope也能够在祖先范围内find这个确切的string值,所以它也显示了对该属性的引用。
在小提琴2中,在打字之前,我们有和fiddle1一样的照片。
inputmy title :

注意新的data.title属性出现在data.title作用域上。 隔离作用域仍然在控制器作用域上查找data.title ,但是这次没有,所以它的title属性值保持为空。
在小提琴3中,在打字之前,我们有和fiddle1一样的照片。
inputmy title :

注意新的data.title属性出现在隔离范围内。 即使data.title作用域可以通过$parent关系访问隔离作用域,但它不会在那里查找title或data.title – 它只会查看控制器作用域(即它将遵循原型inheritance),而控制器作用域没有定义这些属性。
读完所有的答案,包括马克的奇妙的图表,这是我对范围的理解,它是我的问题的inheritance。 我将不胜感激评论这个图下降,以便我可以适当更新。 我希望这只是提供了一个不同的观点,马克提出:

那么问,顺便说一句! 希望我的回答是雄辩的。
答案与如何横穿的元素得到他们的范围。
总而言之,你有两个范围:
- 控制器的范围,其中有
$scope.data.title。 (通过您的input元素隐式添加) - 指令的作用域,其中有
$scope.title。
当你改变控制器的$scope.data.title ,指令的$scope.title也会改变。
你也有两段HTML,transcluded和模板。 所发生的事情就是HTML被包含在控制器的范围之内,并且HTML模板在指令的范围之内。 所以被包含的HTML不知道关于title任何内容,而模板范围对data.title没有任何了解
这实际上就是Transclusion的目的 – 允许一个指令的子元素保留他们的父范围 ,在这个例子中是控制器的范围。 通过devise,transcluded元素不知道他们在一个指令,所以没有访问指令的范围。
另一方面,指令模板只能访问指令的范围。
我已经改变了你的代码,使名称更清晰一些(虽然function相同)