【问题标题】:Why ng-transclude's scope is not a child of its directive's scope - if the directive has an isolated scope?为什么 ng-transclude 的作用域不是其指令作用域的子对象 - 如果指令具有隔离作用域?
【发布时间】:2013-07-22 13:00:24
【问题描述】:

给定一个带有 transclude 和隔离范围的指令 (container1),当该指令被链接时,我就有了这些范围:

Scope 004           <-- scope of the body
    Scope 005       <-- scope of directive container1
    Scope 006       <-- scope of the ng-transclude

我预计:

Scope 004            <-- scope of the body
    Scope 005        <-- scope of the directive
         Scope 006   <-- scope of the ng-transclude

如果同一指令具有共享范围而不是隔离范围,我会得到预期的结果。

这给我带来了一个问题,因为如果转入的内容包含另一个具有隔离范围的指令 (component1),我会得到:

Scope 004             <-- scope of the body
    Scope 005         <-- scope of the directive
    Scope 006         <-- scope of the ng-transclude
          Scope 007   <-- scope of directive component1

我想使用这样的指令:

<container1>
   <component1 data="objectExposedInContainer1"/>
</container1>

但这不起作用,在component1 内部,$scope.dataundefined,因为objectExposedInContainer1 不在正确的范围内。

我有两个问题:

  • 如果指令具有独立作用域,为什么ng-transclude 的作用域不是其指令作用域的子作用域?这是一个错误吗?
  • 如果不是错误,如果不是像我尝试的那样设置属性,容器指令如何将数据传递给它的内容。

这是一个不起作用的示例:http://plnkr.co/edit/NDmJiRzTF9e5gw8Buht2?p=preview。因为 Plunker 是使用 Anguar 构建的,所以很难使用 Batarang 进行调试。我建议在本地下载代码。注释掉 app.jsline 10 以使其使用共享范围。

【问题讨论】:

  • 1) 不,你得到了你想要的——指令的范围是孤立的。 2) 使用共享控制器。
  • @Joe Gauterin,看看这个新样本:plnkr.co/edit/Bv7B4OokkLi8bIctCIl3。这里,container1 包含component1,但没有使用ng-transclude。这一次,即使两者都有独立的作用域,它们的作用域也具有正确的父/子关系。 ng-transclude 的存在会改变结果。

标签: angularjs


【解决方案1】:

如果指令具有独立作用域,为什么 ng-transclude 的作用域不是其指令作用域的子作用域?

ng-transclude 旨在允许指令处理任意内容,而隔离作用域旨在允许指令封装其数据。

如果ng-transclude 没有保留这样的范围,那么您要嵌入的任何任意内容都需要知道指令的实现细节(即,它需要知道您创建的隔离范围上可用的内容)。

如果不是错误,容器指令如何将数据传递给它的内容,如果不是像我尝试的那样设置属性。

如果容器指令和包含的指令是耦合的——即你编写了它们并需要它们一起行动——那么它们应该通过共享控制器进行通信。

如果容器指令应该将内容注入孩子的范围(例如 ng-repeat),那么您不应该使用隔离范围。


角度文档非常清楚该行为应该是什么:

“在典型的设置中,小部件会创建一个隔离范围,但是 嵌入不是一个孩子,而是隔离范围的兄弟。这 使小部件可以拥有私有状态,并且 嵌入要绑定到父(预隔离)范围。”

【讨论】:

  • 感谢您的全面回答。
  • 我创建了一个解决方法,但我不确定最佳实践,我希望你们可以有一些空闲时间来检查一下?这是一个自定义的嵌入黑客,它保证在链接阶段创建一个新的子隔离范围。这将创建父 -> 子层次结构,因此我们可以在控制器中使用 $emit 和 $on。 gist.github.com/meanJim/1c3339bde5cbeac6417d
  • 我也采用了类似于@Jim 的方法,我也不确定这是否是最佳实践。你可以在这里找到一个 plunk:plnkr.co/edit/Ph5lMl0ol8ayXOFr7eal
【解决方案2】:

您可以手动嵌入子元素

link: function(scope, element, attrs, ctrl, transclude) {
    transclude(scope, function(clone, scope) {
        element.find('.transclude-placeholder').append(clone);
    });
}

【讨论】:

  • 如果有一个完整的例子就好了,.transclude-placeholder 是什么?
【解决方案3】:

最佳答案仅适用于 Angular v1.2 之前的版本。

自 Angular v1.3 以来,行为发生了变化,现在它的行为与问题的“我预期”部分中描述的完全一样,使得该问题对于 Angular v1.3+ 已过时。

来源:https://github.com/angular/angular.js/commit/fb0c77f0b66ed757a56af13f81b943419fdcbd7f

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 2016-03-18
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多