【问题标题】:Scope inheritance for angular directives角度指令的范围继承
【发布时间】:2013-10-07 08:20:57
【问题描述】:

我使用角度指令创建了一个选项卡控件。它由具有新范围的 tabtab-item 指令和 tab-item-headertab-item-body 未声明范围的指令。

如果我理解正确,这些指令使用 tab-item 指令的范围,因为它们被放置在其中。但是,当我尝试进入在选项卡项范围内声明的标记属性索引时,它是未定义的。

app.directive('tabItemHeader', function(){
return {
    require: '^tabItem',
    transclude: true,
    template: '<div ng-click="$parent.setCurrentTab(index)" ng-transclude></div>',
};});

app.directive('tabItemBody', function(){
return {
    require: '^tabItem',
    transclude: true,
    template: '<div ng-show="index==$parent.currentTabIndex"><div ng-transclude></div></div>'
};});

我创建了一个 plunk http://plnkr.co/edit/HkXIOt8FKMw4Ja2GZtF1?p=preview 来演示它。

怎么了?

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    (编辑)在 cmets 中的谈话后考虑了一下,我想出了一个更好的解决方案。这是修改后的 plunk:

    http://plnkr.co/edit/djNk8PPzXvngZOvAirMu?p=preview

    这个实现的关键点是:

    • 每个指令都包含其内容。这意味着,正如预期的那样,即使是最内部的指令也可以访问外部范围。所以不要再有$parent.$parent... 可怕了。

    • 每个指令都有一个独立的范围。根据文档,孤立的范围与嵌入的范围并排;因此指令的所有私有状态(在本例中为活动选项卡、每个tabItem 的索引和一些特定于指令的函数)都保持在隔离范围内。

    • 指令通过控制器进行通信。这种模式需要一个顶级的“协调器”(这里是所有后代指令的 tabtabItemHeadertabItemBodytabItem)。

    顺便说一句,如果你想要标签,我建议使用 Angular UI。


    这是一个疯狂的谜题。

    您的问题的原因是 tabItem 指令没有理由嵌入其内容;这个嵌入创建了一个兄弟作用域,完全搞乱了你的逻辑!

    因此答案很简单:从tabItem 指令中删除这些行:

    // REMOVE THEM!!!
    transclude: true,
    template: '<div ng-transclude></div>',
    

    带有这些行的 plunkr 被注释掉并打印范围 ID:http://plnkr.co/edit/bBfEej145s1YjcE9n3Lj?p=preview(这有助于调试;看看当你包含这些行时会发生什么,模板和链接器函数会看到不同的范围!)

    你的 plunkr 分叉了,这些行被注释掉了:http://plnkr.co/edit/tgZqjZk0bRCyZiHKM0Sy?p=preview

    【讨论】:

    • 非常感谢,尼科斯!我想再问你一个关于这段代码的问题。现在指令的范围覆盖控制器的范围,我应该以这种方式使用控制器的变量 {{$parent.$parent.$parent.name}}。但它看起来很可怕。解决此问题的最佳方法是什么?
    • 是的,你是对的。实际上,我刚刚从您的 plunkr 中删除了 $parent(即 template: '&lt;div ng-click="setCurrentTab(index)" ...&gt;)并且它有效。你能做到这一点并验证它确实有效吗? (有一些网络不稳定,我有疑问)
    • 是的。可以从指令模板中删除 $parent。我已经修好了。但是当我想在tab-item-body 指令中使用控制器的name 属性时,我应该编写以下内容:{{$parent.$parent.$parent.name}}(请参阅第一个plunk)。我的问题是是否有办法在不引用父范围的情况下做到这一点?
    • 是的,还是个谜!一种答案是从tab 指令中删除范围。并直接使用父作用域的变量(Plunk:plnkr.co/edit/Of2kIcaGs7DLHyYi2mAK?p=preview)。
    • 我考虑了一下,你说的很对。请参阅顶部的编辑以获得更好的解决方案 - 您最初想要的方式。
    【解决方案2】:

    http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/

    这个网站很好地解释了范围继承。

    基本上,如果您将范围部分添加到您想要的指令中,您有几个选择:

    scope: false # this inherits the parent scope and allows upstream and downstream traffic (parent <=> child)
    scope: true # this inherits the parent scope and allows downstream traffic (parent => child)
    scope: {} # this does not inherit and creates the directive's very own scope (you can still inherit by specifying what you want to come down)
    

    有关通过最后一个选项指定要继承的范围的更多详细信息:What is the difference between & vs @ and = in angularJS

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-04
      • 1970-01-01
      • 2013-09-18
      • 2013-10-04
      相关资源
      最近更新 更多