-2

我正在制作一个自定义指令,并试图使其独立于 jQuery。为了在没有 jQuery 的情况下完成此操作,范围(父级和子级)可能必须直接交互。我当然想尽可能避免“不良做法”,所以我的问题是:

让子作用域直接调用父作用域的函数是不好的做法吗?如果是这样,是否有办法获得控制范围的控制器或元素?

这是必要的原因是指令可能有多个嵌套范围。而且我需要访问一个非常特殊的,不一定是当前范围的直接父级(尽管它是一个祖先)。

编辑:用例详述

该模块包含两个指令。其中任何一个都可以嵌套在任意数量的父指令中。这个子指令确实需要相应的父指令,但是在嵌套父的情况下,它只获取最直接父的控制器。

这个的正常使用一般是:

<element parent-attr-dir="val">
    <element child-attr-dir="val"></element>
</element>

请注意,属性的值必须匹配。这决定了要附加到哪个“祖先”。

高级用法可能类似于:

<element parent-attr-dir="value1">
    <element parent-attr-dir="value2">
        <element child-attr-dir="value1">Will run on top most ancestor</element>
        <element child-attr-dir="value2">Will run on immediate parent</element>
    </element>
    <element parent-attr-dir="value3">
        <element child-attr-dir="value3">Will run on immediate parent</element>
        <element child-attr-dir="value1">Will run on top most ancestor</element>
    </element>
    <element child-attr-dir="val">Will not run!!</element>
</element>

编辑:有问题的解决方案

这有效,但需要知道它是否不好。

var _p = scope;
while (_p !== null) {
    if (_p.doSomething 
    &&  /* some other criteria. */ ) {
        _p.doSomething(scope);
    }
    _p = _p.$parent;
}

编辑:使用 jQuery 的解决方案

这可行,但需要 jQuery,因为 jQLite 没有父(选择器),只有父()。

$(element).parents('[attrname=value]').controller('moduleName').funcName()
4

1 回答 1

2

一种解决方案是让孩子需要父指令,而父母可以选择需要父指令。然后一个子调用它的直接父控制器的方法,传递标准值;如果父控制器不满足条件,它会将调用转发给它自己的父控制器(如果有的话),否则什么也不会发生。解决方案的草图:

app.directive("parentAttrDir", function() {
    return {
        require: ["?^parentAttrDir","parentAttrDir"],
        link: function(scope,elem,attrs,controllers) {
            var parentAttrDir = controllers[0],
                thisController = controllers[1],
                criterion = attrs.parentAttrDir;
            thisController.parent = parentAttrDir;
            thisController.criterion = criterion;
        },
        controller: function($scope) {
            this.doSomething = function(data,criterion) {
                if( this.criterion === criterion ) {
                    // actually do something with the data
                }
                else if( this.parent != null ) {
                    return this.parent.doSomething(data,criterion);
                }
            };
        }
    };
});

app.directive("childAttrDir", function() {
    return {
        require: "^parentAttrDir",
        link: function(scope,elem,attrs,parentAttrDir) {
            var criterion = attrs.childAttrDir;
            // EXAMPLE USAGE FROM CHILD
            scope.doSomeAction = function(data) {
                parentAttrDir.doSomething(data,criterion);
            };
        }
    };
});
于 2013-10-16T14:33:21.230 回答