如何在 AngularJS 指令中更新 class
How to update class in AngularJS directive
我想在点击指令时更改 class(内部指令),
这是我当前的代码,其中 scope.myattr
在控制台中更新但不在模板或视图中更新:
<test order="A">Test</test>
.directive("test", function () {
return {
restrict: 'E',
scope: {
myattr: "="
},
transclude: true,
link: function (scope, element, attrs) {
scope.myattr = attrs.myattr;
element.bind('click', function () {
console.log(scope.myattr);
if (scope.myattr == 'A') {
scope.myattr = 'B';
}
else {
scope.myattr = 'A';
}
});
},
template: `
<span ng-transclude></span>
<span class="sortIcon {{myattr}}">{{myattr}}</span>`
}
});
您的问题是关于使用 $apply
方法执行摘要循环。
替换此行:scope.myattr = attrs.myattr;
通过这个:
scope.$apply(function(){
scope.myattr = attrs.myattr;
});
这会手动强制在作用域上发生摘要循环,这将运行遍历其所有观察者并查找更改。
记住在该范围内进行所有更新。
希望对您有所帮助!
我认为它可以与添加 class 和删除 class 一起使用。额外的好处是你没有 "polluting" HTML 括号,一切都在控制器
测试
.directive("test", function () {
return {
restrict: 'E',
scope: {
myattr: "="
},
transclude: true,
link: function (scope, element, attrs) {
scope.myattr = attrs.myattr;
elem.bind('click', function (e) {
if (scope.myattr == 'A') {
angular.element(e.target).removeClass('A');
angular.element(e.target).addClass('B');
}
if (scope.myattr == 'B') {
angular.element(e.target).removeClass('B');
angular.element(e.target).addClass('A');
}
});
});
},
template: `
<span ng-transclude></span>
<span class="sortIcon">{{myattr}}</span>`
}
});
如果你想用代码污染 HTML 然后选择 ng-class
指令。它旨在用于 class 表达式并提供更多选项,然后直接绑定 class 名称。
我建议不要使用 $apply,因为当您强制执行摘要循环时,您会 运行 遇到很多问题。具体来说,如果当前正在 运行ning,则您不能中断并开始新的摘要循环。 Angular 在这种情况下会抛出错误。显式摘要循环也会对性能产生负面影响,因为它必须 运行 一个循环来检查所有范围变量以查看发生了什么变化。我建议使用 "ng-class" 作为基于 类.
的表达式
只有在 Angular 上下文之外更改范围变量时,才需要手动 运行 摘要循环,如下文所述。
https://www.sitepoint.com/understanding-angulars-apply-digest/
而且我认为您当前的强制摘要循环解决方案仅适用于您的双向数据绑定,因为由于您指定 ng-transclude 的方式,它不在您的指令范围内。最好有适当的范围结构,不要强制任何摘要循环,因为指令有自己的摘要循环。
我想在点击指令时更改 class(内部指令),
这是我当前的代码,其中 scope.myattr
在控制台中更新但不在模板或视图中更新:
<test order="A">Test</test>
.directive("test", function () {
return {
restrict: 'E',
scope: {
myattr: "="
},
transclude: true,
link: function (scope, element, attrs) {
scope.myattr = attrs.myattr;
element.bind('click', function () {
console.log(scope.myattr);
if (scope.myattr == 'A') {
scope.myattr = 'B';
}
else {
scope.myattr = 'A';
}
});
},
template: `
<span ng-transclude></span>
<span class="sortIcon {{myattr}}">{{myattr}}</span>`
}
});
您的问题是关于使用 $apply
方法执行摘要循环。
替换此行:scope.myattr = attrs.myattr;
通过这个:
scope.$apply(function(){
scope.myattr = attrs.myattr;
});
这会手动强制在作用域上发生摘要循环,这将运行遍历其所有观察者并查找更改。
记住在该范围内进行所有更新。
希望对您有所帮助!
我认为它可以与添加 class 和删除 class 一起使用。额外的好处是你没有 "polluting" HTML 括号,一切都在控制器
测试
.directive("test", function () {
return {
restrict: 'E',
scope: {
myattr: "="
},
transclude: true,
link: function (scope, element, attrs) {
scope.myattr = attrs.myattr;
elem.bind('click', function (e) {
if (scope.myattr == 'A') {
angular.element(e.target).removeClass('A');
angular.element(e.target).addClass('B');
}
if (scope.myattr == 'B') {
angular.element(e.target).removeClass('B');
angular.element(e.target).addClass('A');
}
});
});
},
template: `
<span ng-transclude></span>
<span class="sortIcon">{{myattr}}</span>`
}
});
如果你想用代码污染 HTML 然后选择 ng-class
指令。它旨在用于 class 表达式并提供更多选项,然后直接绑定 class 名称。
我建议不要使用 $apply,因为当您强制执行摘要循环时,您会 运行 遇到很多问题。具体来说,如果当前正在 运行ning,则您不能中断并开始新的摘要循环。 Angular 在这种情况下会抛出错误。显式摘要循环也会对性能产生负面影响,因为它必须 运行 一个循环来检查所有范围变量以查看发生了什么变化。我建议使用 "ng-class" 作为基于 类.
的表达式只有在 Angular 上下文之外更改范围变量时,才需要手动 运行 摘要循环,如下文所述。
https://www.sitepoint.com/understanding-angulars-apply-digest/
而且我认为您当前的强制摘要循环解决方案仅适用于您的双向数据绑定,因为由于您指定 ng-transclude 的方式,它不在您的指令范围内。最好有适当的范围结构,不要强制任何摘要循环,因为指令有自己的摘要循环。