在使用AngularJS制作错误消息指令时,我一直在努力解决范围问题.
我有一个ng-if和ng-class指令作为指令模板的一部分,但ng-class指令中的表达式似乎总是返回一个空字符串,除非:
>我删除了ng-if指令.
>或者,我删除了指令定义对象中的’replace’键.
查看我的指令的编译输出,如果删除了ng-if或replace键,看起来像是创建了一个隔离的范围,但是如果它们都被保留,那么就没有ng-isolate-scope类. html输出,只是ng-scope.
我真的很想了解到底发生了什么,并对任何解释感激不尽.
指令定义
angular.module('myMessages') .directive('pageMessages',function() { return { restrict: 'E',replace: true,scope: { messages: '=' },controller: function($scope) { $scope.severity = 'alert-success'; },template: '<div ng-if="messages.length > 0">' + '<div class="alert" ng-class="severity">' + '<ul>' + '<li ng-repeat="m in messages">{{::m.message}}</li>' + '</ul>' + '</div>' + '</div>' }; });
<!-- ngIf: messages.length > 0 --> <div ng-if="messages.length > 0" messages="messages" class="ng-scope"> <div class="alert" ng-class="severity"> <ul> <!-- ngRepeat: m in messages --> <li ng-repeat="m in messages" class="ng-binding ng-scope">test error</li> <!-- end ngRepeat: m in messages --></ul> </div> </div> <!-- end ngIf: messages.length > 0 --></div>
删除替换后添加alert-danger类(删除ng-if也可以)
<page-messages messages="messages" class="ng-isolate-scope"> <!-- ngIf: messages.length > 0 --> <div ng-if="messages.length > 0" class="ng-scope"> <div class="alert alert-danger" ng-class="severity"> <ul> <!-- ngRepeat: m in messages --> <li ng-repeat="m in messages" class="ng-binding ng-scope">test error</li> <!-- end ngRepeat: m in messages --> </ul> </div> </div> <!-- end ngIf: messages.length > 0 --> </page-messages>
解决方法
truthy ng-if的工作是克隆原始元素并赋予其继承范围.它使用transclusion,这允许ng-if在具有隔离范围的元素上获取继承范围,避免$multiple:multidir错误,Multiple指令请求新的/隔离范围判定.
好处是,如果在具有隔离范围的元素上使用它,它将不会抛出错误.不好的是,当用于具有更高优先级的指令(ng-如果优先级为600)时,它将仅替换它,忽略其范围.另一个坏处是,当在带有隔离范围的指令的根模板元素上使用时(就像这一个),它只会用克隆的元素替换一个从父范围继承其范围的元素(属于指令的父元素,因为它自己的元素已被替换为替换).
因此,它只从pageMessages父作用域获取严重性值,并将ng-class表达式计算为空字符串(如果它不存在).
解决方案是不要在带有replace标志的指令的根元素上使用ng-if.替换标志has got deprecation status,这意味着issues won’t be fixed.当指令的模板获得额外的< div>包装(尽管它可能违背替换目的),一切都应按预期工作.