这个问题已经很老了,所以你可能找到了答案,但我仍然会尝试解释它,因为其他人可能会觉得它很有用。
在使用隔离范围和使用ng-transclude
指令嵌入内容时,需要记住三件事。
- 隔离范围意味着它不继承其父级的属性。它仅继承您在范围对象内显式绑定的属性。
- 嵌入的内容只有在插入后才会被编译和链接。
ng-transclude
创建包含内容的指令的新同级范围。虽然,这可能会从版本 1.3.0 更改ng-transclude 不应创建新的同级范围。
了解示例中发生的情况的最佳方法是查看您的范围树。
< Scope (002) : ng-app
< Scope (003) ng-controller
< Scope (004) : b
< Scope (005) : ng-transclude <--- Content rendered under this scope
< Scope (006) : aIsolated
< Scope (007) : b
< Scope (008) : ng-transclude
< Scope (009) : ng-transclude <--- Content rendered under this scope
< Scope (00A) : aNotIsolated
< Scope (00B) : b
< Scope (00C) : ng-transclude
< Scope (00D) : ng-transclude <--- Content rendered under this scope
在您的第一个示例中,Angular 找到了b
指令。它提取内容,创建一个隔离范围并编译其模板。编译模板时,它会找到ng-transclude
指令。它创建一个新的同级作用域并将内容插入其中。由于ng-transclude
的作用域是同级,它的父级是ng-controller
. 因此,内容继承了MainCtrl
控制器的所有属性。
在第二个例子中,Angular 找到了aIsolated
指令。它提取内容,创建一个隔离范围并编译其模板。编译模板时,它会找到b
指令并开始编译b
。它撕下指令包装的内容b
,为模板创建一个独立的子范围b
并编译模板。编译b
模板时,它会找到ng-transclude
指令。它创建一个新的同级作用域并将内容插入其中。即这个新的同级作用域被传递给一个transclude
使内容成为ng-transclude
作用域子级的函数。然后它开始编译它找到另一个指令的内容,因此它创建一个新的范围并使用和ng-transclude
插入内容{{message}}
{{private}}
表达进去。最后是编译和链接表达式。但是如果你查看继承树你会发现内容继承了作用域的属性aIsolated
,这将我们带到了孤立的作用域。
aIsolated
指令具有隔离范围,因此它无法访问private
父范围中定义的属性,因此内容会读取您在aIsolated
控制器中定义的属性。然后,指令b
也创建了一个隔离范围并向其中添加了一个private
属性,但是因为它是隔离的,所以它不会覆盖其父级的属性。因此,当所有指令完成编译和链接后,指令中定义的属性将aIsolated
被放入{{message}}
和{{private}}
表达式中。message
属性不存在,所以它是空的。
第三个例子的编译过程和第二个完全一样。它仅与指令不同,该aNotIsolated
指令简单地创建自己的范围,从而继承MainCtrl
控制器中定义的属性。
如果指令的范围不是孤立的,那么私有属性不会泄漏并显示问候语。
这并不完全正确。它可能以这种方式出现的原因是因为aNotIsolated
没有定义自己的private
属性。在我的示例 aNotIsolated
中,在其控制器中定义了private
属性,因此您可以看到私人消息与您的示例不同。
泄漏也不是描述正在发生的事情的好词。表达式在它们被插入的范围内进行评估。所以{{message}}
and{{private}}
表达式在作用域下进行评估,ng-transclude
而作用域又继承自MainCtrl
,aIsolated
或aNotIsolated
作用域。