我的应用程序中有一些DOM元素加载相当昂贵,所以我一直在使用以下模式来确保在需要之前不加载它们:
<div ng-if="someCondition || everShown" ng-show="someCondition">
基本上,这确保元素仅在someCondition为真时添加到DOM,然后保留在那里。但是,那里有相当多的重复逻辑,因此我想将逻辑提取到指令中。
这是我的尝试:
export function IfEverShown($parse: angular.IParseService): angular.IDirective {
return {
restrict: "A",
compile: function(element: angular.IAugmentedJQuery,
attributes: angular.IAttributes) {
if (!attributes["ngShow"]) {
return;
}
element.attr("ng-if", "everShown");
return {
pre: function(scope: angular.IScope) {
scope["everShown"] = false;
attributes.$observe('ngShow', function (expr) {
scope.$watch(function () {
return $parse(<any> expr)(scope);
}, function (value) {
if (value) {
scope["everShown"] = true;
}
});
});
}
};
}
};
}
然后使用:
<div ng-show="someCondition" if-ever-shown>
但是,即使DOM中的ng-if值按预期更改,Angular也会忽略其上的更改:如果之前没有ng-if,则该元素始终存在于DOM中,如果存在以前的值,即使在我改变它之后也会被观察到。
我怎么能在这里得到理想的行为?我可以从指令修改ngIf吗?否则,是否有其他方法可以确保在ng-show条件至少为真之前元素不会被添加到DOM中?
谢谢!
答案 0 :(得分:1)
$compile service不会自动编译在编译阶段添加到元素的指令。任何新添加的指令都需要在链接阶段手动编译:
app.directive("myIf", function($compile) {
return {
priority: 1000,
terminal: true,
compile: function(tElem, tAttrs) {
tAttrs.$set("ngIf", tAttrs.myIf);
tAttrs.$set("myIf", null);
return postLink;
}
}
function postLink(scope, elem, attrs) {
$compile(elem)(scope);
}
});
上面的示例演示了一个名为my-if
的自定义指令。它在编译阶段添加了ng-if
指令,并在链接阶段手动编译它。
请注意,它是作为高优先级"terminal"
指令实现的,它删除了my-if
属性,因此指令只编译一次。