[英]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>
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>'
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.