【问题标题】:Using isolate scope and embedded directive controllers together一起使用隔离范围和嵌入式指令控制器
【发布时间】:2014-04-07 19:15:35
【问题描述】:

我一直在使用指令,但我正在尝试使用隔离范围来构建它们。

我很难理解如何将隔离范围与指令控制器结合使用。似乎一旦我隔离了作用域,模板就不能再访问指令控制器上的作用域函数了。

这是一个例子:

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

我已阅读有关使用范围绑定的信息,但它似乎应该用于与“父”范围进行交互,并且我认为嵌入式控制器将成为隔离范围的一部分。

【问题讨论】:

  • 认真思考孤立这个词。这是将指令的范围与其父范围分开并创建一个新的隔离范围。执行此操作时,您需要在指令定义对象的范围属性中指定指令需要访问的所有内容。如下所述,您可以使用 = 以两种方式绑定某个属性,或者如果您希望该属性在其起源的范围内作为函数执行,则可以使用 &。

标签: javascript angularjs angularjs-directive angularjs-scope


【解决方案1】:

这对新手来说是个难题。我准备在这里做一份简历让大家看懂。

当你在做类似的事情时:

<my-directive>
  <button ng-click="doSomething()">Do Something</button>
</my-directive>

您的第一个想法是 &lt;my-directive&gt; 中的所有内容,在这种情况下 &lt;button&gt; 是指令的一部分。这不是真的。

同样,&lt;button&gt; 内部的内容称为transcluded htmltranscluded html 有一个新作用域,它无法访问指令的隔离作用域,实际上它们是兄弟姐妹。

具体来说,有一个控制器的作用域,从那里有一个隔离作用域和一个新的作用域用于被嵌入的 html。

因此,由于嵌入的 html 无法访问隔离范围,ng-click 根本不会触发。

有解决方法。

所以在这种情况下,我重复一遍,doSomething 存在于隔离范围内,并且该按钮正在查看 transcluded html 及其父级(控制器的范围)的新范围,但它不存在。

sh3nan1gans 给你的解决方案是有效的,但我个人不会这样做。

它是如何工作的?由于它创建了与控制器范围的双向绑定,因此它在隔离上创建新函数,然后也在父级上创建它。然后按钮将在该父范围内找到该函数,然后运行它。

如果您想了解更多信息,包括解决方法,请查看here

【讨论】:

  • 很好的解释。我不会说嵌入的内容范围和孤立的内容范围是兄弟。他们是父母和孩子。因此,作为一种非常快速且糟糕的解决方法,您可以使用 $$childHead.doSomething() 访问隔离的内容范围 doSomething 方法。
  • 他们不是。它们都是父作用域的子元素。
  • 抱歉坚持,但下面给出了trueangular.element($0).scope().$$childHead == angular.element($0).data('$isolateScopeNoTemplate') 其中$0 是包含指令实例的元素。当然,我只关心 Angular >= 1.2.0 (>1.2.0rc3),他们在隔离范围和指令嵌入方面做出了重大改变。
【解决方案2】:

将该函数添加到您的 html 中的指令中:

<my-directive do-something="doSomething">
  <button ng-click="doSomething()">Do Something</button>
</my-directive>

在你的指令文件中:

scope: {
    doSomething: '='
  }

更新的插件: http://plnkr.co/edit/0qxipiBvVFEC1huBPGNM?p=preview

【讨论】:

    【解决方案3】:

    因为您的按钮在您编译新指令和隔离范围之前就在那里,它们被分配给父范围而不是您正在创建的新范围。如果您希望将按钮附加到新范围,则需要使用可注入的 transclude 和链接器函数来移动 html 并将其编译到新范围,如下所示:

    angular.module('directives',[]) .directive('myDirective', function(transclude) { return { restrict: 'E', transclude: true, scope: {}, controller: function($scope, $element, $attrs, ctrl, transclude) { transclude(function(clone){ $element.append(clone); $scope.doSomething = function() { alert('I did something'); } }); } } });

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多