0

我正在使用 vanilla AngularJS v1.4.5(无 jQuery),并希望我的自定义指令在编译时向其祖父元素添加一个属性。

在编译函数中,我可以使用两次获取祖父元素的方法和添加我的属性的方法来parent()实现这一点。但是,如果元素具有ngIf指令,则祖父元素不会获得该属性。elementattr()

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');
    }
}

JSFiddle

这是我所知道的:

  • 如果ngIf未在父元素上使用,则该属性将添加到祖父元素。
  • 问题不应该与 相关scope,因为这是在编译阶段发生的,在作用域被链接到任何元素之前。
  • 我的 compile 函数应该在 of 之前运行ngIf,它的优先级为600(并且没有 compile function)。
  • ngIf完全删除并重新创建 DOM 中的元素(连同其子元素),但这不应影响祖父元素或更改其属性。

如果父元素具有指令,谁能向我解释为什么我不能向指令的祖父元素添加属性ngIf

4

2 回答 2

2

所以,重申一下,问题是,为什么给出以下内容:

<grand-parent>
  <parent ng-if="condition">
    <foo></foo>
  </parent>
</grand-parent>

当尝试var grandparent = tElement.parent().parent()从 的编译中检索时foograndparent不引用该<grand-parent>元素。

答案是由于 - 导致的ngIf嵌入,即使condition === true.

嵌入是将内容(或元素+内容,取决于嵌入的类型)从 DOM 中拉出、编译,然后作为克隆提供给嵌入函数的过程,该函数本身可以作为函数的第五个参数link

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。因为ngIfhas transclude: "element",它<parent><foo></foo></parent>从 DOM 中抽出,并对其进行编译。因此,编译继续编译其他低优先级指令(如果可用) on <parent>,然后编译foo指令。

至此,<foo>不下<grand-parent>tElement.parent().parent()让步[]

于 2015-09-17T04:40:17.753 回答
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 操作。

于 2015-09-16T23:40:04.080 回答