如何阻止&的传播函数嵌套指令

时间:2013-12-15 10:10:12

标签: angularjs angularjs-directive angularjs-scope

这里我有一个ctrl

controllers.ctrl = function($scope){

 $scope.trData = [
  {name : 'elem1',children : []},
  {name : 'elem2',children : 
     [{name : 'elem3',children : []}]
  }
 };


 $scope.testFunction = function(tr){
  console.debug(tr);
 }
}

嵌套指令

directives.nested = function($compile){
  restrict: 'E',
    replace: false,        
    scope: {
        tr: '=',
        test : '&'
    },
    link: function(scope, element, attrs) {  

        scope.setActive = function(){
            console.debug("A");
            console.debug(scope.tr);
            scope.test({tr:scope.tr});
            console.debug("B");
        };

        var template = '<span data-ng-click="setActive();">{{tr.name}} - </span>';

        if(scope.tr.children.length > 0){
            template += '<ul><li data-ng-repeat="tr0 in tr.children">';
            template += '<nested  tr="tr0" test="test(tr)"></nested>';
            template += '</li></ul>';
        }
        var newElement = angular.element(template);
        $compile(newElement)(scope);
        element.replaceWith(newElement);
}

当然,在我的模板中:

<ul>
 <li data-ng-repeat="tr in trData">
  <nested tr="tr" test="testFunction(tr)"></nested>
 </li>
</ul>

当我点击elem1时,我已进入控制台:

A
{name : 'elem1',children : []}
B

如果我点击'elem3',我就

A
{name : 'elem3',children : []}
{name : 'elem2',children : [{name : 'elem3',children : []}] }
B

函数testFunction被调用两次。我想用elem3只调用一次。

我相信有更好的方法可以做到这一点。

来自Banana-In-Black的小提琴:http://jsfiddle.net/T4uKf/

1 个答案:

答案 0 :(得分:1)

更新

  

尝试点击elem3:您将看到console.debug输出&#39;对象   {name:&#34; elem3&#34;,children:Array [0]&#39;而console.warn输出:   对象{名称:&#34; elem2&#34;,孩子:数组[1]我虽然会有&#34; elem3&#34;   输出两次。相反,我得到了&#34; elem3&#34;和&#34; elem2&#34;。你知道为什么吗?   会发生什么?

首先,我们先看一下生成的HTML和范围:

                                                <!-- controller scope       -->
<li data-ng-repeat=" tr in trData ">            <!--1|-child scope          -->
    <span>elem2 - </span>                       <!--2  |-isolated scope     -->
    <ul>                                        <!--     |                  -->
        <li data-ng-repeat="tr0 in tr.children"><!--3    |-child scope      -->
            <span>elem3</span>                  <!--4      |-isolated scope -->
        </li>
    </ul>
</li>

范围内的变量如下:(|-代表继承)

  • 控制器范围:{ trData: [...] }
    • | - Scope1(孩子):{ tr0: elem2 }
  • 范围2(隔离):{ tr: elem2, test: function() }
    • | - Scope3(孩子):{ tr0: elem3 }
  • Scope4(隔离):{ tr: elem3, test: function() }


现在,根据official api docs,它讨论了孤立的范围变量:

  

&安培;或&amp; attr - 提供了一种在父作用域的上下文中执行表达式的方法。

*此功能由$parse服务实施。

点击elem3后,执行顺序为:(跳过日志部分。)

  1. test({ tr: scope.tr })使用Scope4作为执行上下文
    • 等于$parse('test(tr)')(Scope3, { tr: elem3 })
    • Scope3中调用它,因为$parse在父范围内执行。
  2. test(tr)使用Scope3作为执行上下文
    • 等于$parse('testFunction(tr)')(Scope1, elem3)
    • Scope1中调用它,因为test()继承自Scope2,而$parse在父范围内执行。
  3. testFunction(tr)使用Scope1作为执行上下文
    • 现在tr将被解析为Scope1.tr elem2,因为elem3.tr不存在。
  4. 最后,console.warn(elem2);
  5. 这就是这种情况......

    *关于$ parse服务,您可以查看this


    产地:

    我将console.log更改为console.warn,ang日志显示它只执行一次。

     $scope.testFunction = function (tr) {
         console.warn(tr);
     }
    

    http://jsfiddle.net/T4uKf/

    打印两次

    A
    {name : 'elem3',children : []}
    {name : 'elem2',children : [{name : 'elem3',children : []}] }
    B
    

    只是因为您在scope.setActive$scope.testFunction()

    中都记录了它