这个问题已经很老了,所以你可能找到了答案,但我仍然会尝试解释它,因为其他人可能会觉得它很有用。
在使用隔离范围和使用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作用域。