混淆了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个绑定?

我希望有一些明显的盯着我,我很想念它。 如果你让我得到这个,我会给你买一瓶啤酒,或者给你一些点数,或者其他的一些东西。 非常感谢。

你的小提琴创造了三个范围:

  1. 由于ng-controller ,与控制器Ctrl相关的范围
  2. 一个指令transcluded作用域,因为transclude: true
  3. 一个指令隔离范围,由于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关系访问隔离作用域,但它不会在那里查找titledata.title – 它只会查看控制器作用域(即它将遵循原型inheritance),而控制器作用域没有定义这些属性。

读完所有的答案,包括马克的奇妙的图表,这是我对范围的理解,它是我的问题的inheritance。 我将不胜感激评论这个图下降,以便我可以适当更新。 我希望这只是提供了一个不同的观点,马克提出:

范围继承

那么问,顺便说一句! 希望我的回答是雄辩的。

答案与如何横穿的元素得到他们的范围。

总而言之,你有两个范围:

  1. 控制器的范围,其中有$scope.data.title 。 (通过您的input元素隐式添加)
  2. 指令的作用域,其中有$scope.title

当你改变控制器的$scope.data.title ,指令的$scope.title也会改变。

你也有两段HTML,transcluded和模板。 所发生的事情就是HTML被包含在控制器的范围内,并且HTML模板在指令的范围内。 所以被包含的HTML不知道关于title任何内容,而模板范围对data.title没有任何了解

这实际上就是Transclusion的目的 – 允许一个指令的子元素保留他们的父范围 ,在这个例子中是控制器的范围。 通过devise,transcluded元素不知道他们在一个指令,所以没有访问指令的范围。

另一方面,指令模板只能访问指令的范围。

我已经改变了你的代码,使名称更清晰一些(虽然function相同)

http://jsfiddle.net/yWWVs/2/