我使用的是vanilla AngularJS v1.4.5(没有jQuery),并希望我的自定义指令在编译时为其祖父元素添加一个属性。
在编译函数中,我可以使用parent()
方法element
两次来获取祖父元素,并使用attr()
方法来添加我的属性。但是,如果 parent 元素具有ngIf指令,则祖父表元素不会获取该属性。
angular.module('myApp', [])
.directive('foo', fooDirective)
;
function fooDirective() {
return {
compile : compile,
priority: 601 // ngIf is 600
};
function compile(element, attrs) {
var parent, grandparent;
parent = element.parent();
grandparent = parent.parent();
parent.attr('foo', 'bar');
grandparent.attr('foo', 'bar');
}
}
以下是我所知道的:
ngIf
,则该属性会添加到祖父母。scope
有关,因为这是在编译阶段,在范围与任何元素相关联之前发生的。ngIf
之前运行,优先级为600
(和doesn't have a compile function)。ngIf
完全删除并重新创建DOM中的元素(及其子元素),但这不应影响祖父元素或更改其属性。如果父元素具有ngIf
指令,有人可以向我解释为什么我不能在我的指令的祖父元素中添加属性吗?
答案 0 :(得分:2)
所以,重申一下,问题是,为什么给出以下内容:
<grand-parent>
<parent ng-if="condition">
<foo></foo>
</parent>
</grand-parent>
尝试从var grandparent = tElement.parent().parent()
的编译中检索foo
时,grandparent
不会引用<grand-parent>
元素。
答案是因为ngIf
导致的转换,即使condition === true
也是如此。
翻译是这样一个过程,其中内容(或元素+内容,取决于翻译的类型)被从DOM中挖出,编译,然后作为克隆提供给翻译功能,该翻译功能本身可用作link
函数的第5个参数:
link: function(scope, element, attrs, ctrls, transcludeFn){
transcludeFn(scope, function cloneAttachFn(clonedContent){
// clonedContent is the subtree that was transcluded, compiled and cloned
element.append(clonedContent);
});
}
因此,编译过程从<grand-parent>
开始,然后转到<parent>
,在那里它看到一个指令 - ngIf
。由于ngIf
有transclude: "element"
,因此它会将<parent><foo></foo></parent>
从DOM中删除,然后编译它。因此,编译继续编译<parent>
上的其他低优先级指令(如果可用),然后编译foo
指令。
此时,<foo>
不在<grand-parent>
下,tElement.parent().parent()
收益[]
。
答案 1 :(得分:0)
我不完全确定为什么会发生这种情况,但是你有什么特别的理由为什么要用编译来做这件事?我调整了你的指令以使用链接,它似乎工作正常。
(function () {
'use strict';
angular.module('myApp', [])
.directive('foo', fooDirective)
;
function fooDirective() {
return {
link : link,
priority: 601 // ngIf is 600
};
function link($scope, element, attrs) {
var parent, grandparent;
parent = element.parent();
grandparent = parent.parent();
parent.attr('foo', 'bar');
grandparent.attr('foo', 'bar');
}
}
})();
编辑: 就像@NewDev所说的那样,你通常应该在链接阶段而不是在编译期间进行DOM操作。