简体   繁体   English

在另一个指令中使用ngClass指令会引发控制台错误

[英]Using an ngClass Directive Inside Another Directive Throws Console Error

I am trying to use ngClass inside my directive, and it is working but I am seeing a console error: 我试图在我的指令中使用ngClass,它正在工作,但我看到一个控制台错误:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

Here is a simplified version of my directive which reproduces the issue: 这是我的指令的简化版本,它重现了这个问题:

angular.module('myApp', [])
    .directive('myDirective', function () {
    return {
        restrict: 'E',
        scope: {
            myNgClass: '='
        },
        template: '<div ng-class="myNgClass">Hello World</div>'
    }
});

And here is how I am using it: 这是我如何使用它:

<my-directive my-ng-class="{'green':true}"></my-directive>

And here is a link to a jsFiddle. 这里是jsFiddle的链接。

So, first of all, this error is specific to the version of Angular that you are using (v1.2.1) - it was fixed in v1.2.5 ( working demo with v1.2.5). 因此,首先,此错误特定于您正在使用的Angular版本(v1.2.1) - 它已在v1.2.5(使用v1.2.5的工作演示)中修复。

Second, you really shouldn't be using a two-way binding ( "=" ) since you don't seem to need to change the value from inside the directive. 其次,你真的不应该使用双向绑定( "=" ),因为你似乎不需要更改指令内的值。 Using "=" unnecessarily creates 2 watchers. 使用"="不必要地创建2个观察者。

You could definitely do one-way string binding ( "@" ), like so: 你绝对可以做单向字符串绑定( "@" ),如下所示:

scope: {
  myNgClass: '@'
},
template: '<div ng-class="{{myNgClass}}">Hello World</div>'

but this will have a more limited use. 但这将是一个更有限的用途。 For example you won't be able to pass a object ( $scope.greenStyle = { green: true }; ) to your directive: 例如,您将无法将对象( $scope.greenStyle = { green: true }; )传递给您的指令:

<my-directive my-ng-class="greenStyle"></my-directive>

It is better to use a one-way binding to expressions - "&" . 最好使用单向绑定表达式 - "&" This keeps a single watch and binds to an object - not string. 这样可以保留一只手表并绑定到一个对象 - 而不是字符串。 scope.myNgClass becomes a function that returns the value of the bound expression: scope.myNgClass成为一个返回绑定表达式值的函数:

scope: {
  myNgClass: '&'
},
template: '<div ng-class="myNgClass()">Hello World</div>'

Demo 演示

Use @ instead of = . 使用@而不是=

myNgClass: '@'

When you use = angular adds a $watch for changes to 'myNgClass'. 当你使用= angular时添加一个$ watch来改变'myNgClass'。 When a $watch is added, angular adds $$hashKey to the object and "attempts" to assign the modified object back to where it came from (so that the source and destination have the same object). 当添加$ watch时,angular会将$$ hashKey添加到对象,并“尝试”将修改后的对象分配回其来源(以便源和目标具有相同的对象)。

The problem is when the $digest compares the object it has {'green':'true', $$hashKey: '123546246'} vs the evaluated expression {'green':'true'} the comparison fails so the $watch listener is run (NOTE: That part is just my theory. I don't know 100% that it's adding a hashKey, but i DO know that it's treating the objects as different instances and that's triggering the watch listener). 问题是当$ digest比较它具有{'green':'true', $$hashKey: '123546246'}与评估的表达式{'green':'true'}比较失败时所以$ watch listener运行(注意:那部分只是我的理论。我不知道100%它正在添加一个hashKey,但我知道它将对象视为不同的实例并且触发了监听器)。 Since my-ng-class will always send back a new instance of that object it will always be different and will always trigger the watch listener. 由于my-ng-class将始终发送回该对象的新实例,因此它将始终不同并始终触发监视侦听器。

If you want to keep using = you can (but there's no need). 如果你想继续使用=你可以(但没有必要)。 You just have to define your initial object once elsewhere before passing it in. You can use ng-init to do that, like this: 你只需要在传入它之前在其他地方定义你的初始对象。你可以使用ng-init来做到这一点,如下所示:

<my-directive ng-init="clazz={'green':'true'}" my-ng-class="clazz"></my-directive>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM