如何在AngularJS的递归指令中传递函数引用?
我有这个指示:如何在AngularJS的递归指令中传递函数引用?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我有这个指示: app.directive('recursiveListItem', ['$http', 'RecursionHelper', function ($http, RecursionHelper) { return { restrict: 'E', scope: { parent: '=', onNodeClick: '&', }, compile: fu
app.directive('recursiveListItem', ['$http', 'RecursionHelper', function ($http, RecursionHelper) {
return {
restrict: 'E',
scope: {
parent: '=',
onNodeClick: '&',
},
compile: function (element, attributes) {
return RecursionHelper.compile(element);
},
template:
'<div class="list-group-item-heading text-muted parent "> \
<input type="checkbox" data-ng-click="visible = !visible" id="{{parent.Name}}">\
<label for="{{parent.Name}}"> </label>\
<a href="javascript:void(0)" data-ng-click="onNodeClick({node: parent})">{{parent.Name}}</a> \
</div> \
<ul data-ng-if="parent.Children.length > 0" data-ng-show="visible"> \
<li ng-repeat="child in parent.Children"> \
<recursive-list-item data-parent="child" data-on-node-click="onNodeClick"></recursive-list-item> \
</li> \
</ul>',
};
}]);
每件事都像一个符咒,但我没有让我的在节点上点击工作。对于所有根项目,“回调”工作正常,但从那时起,所有子项都不会启动回调。我认为这与将函数引用传递给模板中的下一个子级有关
我还尝试了在node click=“onNodeClick(node)”
上使用数据,但这也不起作用
有人知道如何将函数引用传递给子节点吗?根本问题
作为一个有助于了解“&”的导语,该词是这样描述的:
&or&attr-提供在的上下文中执行表达式的方法
父范围
通常需要通过
表达式和父作用域,这可以通过传递映射来完成
将局部变量名称和值的。对于
例如,如果表达式是increment(amount),那么我们可以指定
通过将localFn调用为localFn({amount:22})的amount值
为了实现这一点,通过&
传递的函数被包装在另一个函数parentGet()
中。通过查看click handler函数变量的内容,我们可以看到这一点。首先,在它被传递到和之前,正如我们所期望的:
function (node) {
console.log("called with ",node);
}
但是,在您的指令中,在通过“&”之后,它看起来是这样的:
function (locals) {
return parentGet(scope, locals);
}
因此,不再直接引用click handler函数,而是使用父作用域和传入的任何局部变量来应用函数的调用
问题是,据我所知,当我们嵌套范围变量时,会不断更新到新的嵌套父范围。那对我们不好。我们希望执行上下文是单击处理程序所在的顶级作用域。否则我们就失去了对你函数的引用——正如我们所看到的那样
解决方案
为了解决这个问题,我们保留了对原始函数的引用(当我们嵌套时,它不会受到parentGet()
的阻碍)。然后,当我们传入它时,parentGet()
中使用的作用域就是带有click handler函数的作用域
首先,让我们为实际函数使用与参数不同的名称。我将函数设置为so$scope.onNodeClickFn=function(node){…}
然后我们做3个改变:
1)添加第二个范围变量(topFunc
):
onNodeClick
是包装函数(包括范围参数)。而topFunc
是对unwrapped函数的引用(请注意,我们在使用=
时传递了它,因此它是对&
应用的没有包装的函数的引用)
2)在顶层,我们传入两个函数引用
<recursive-list-item on-node-click="onNodeClickFn(node)" top-func="onNodeClickFn" parent=parent ></recursive-list-item>
因此,我们现在在每个嵌套范围中维护对原始函数的引用,并在模板中使用该引用
你可以看到它在这把小提琴中工作:我只是用一个调查问卷应用程序做了同样的事情,我保持函数在各个级别的隔离范围内传递的方式是将函数放在函数({param:param})符号中的每个项中
在您的应用程序中,也可以是:
<ul data-ng-if="parent.Children.length > 0" data-ng-show="visible"> \
<li ng-repeat="child in parent.Children"> \
<recursive-list-item data-parent="child" data-on-node-click="onNodeClick({param:param})"></recursive-list-item> \
</li> \
</ul>',
在指令控制器中,您也可以调用它:
onNodeClick({param1: value1, param2:value2})
否则,如果onNodeClick仅影响主控制器(添加指令的页面)中的变量,则可以将主控制器作用域中存在参数的函数名传递给指令,并在指令控制器中不使用参数的情况下使用该函数。Thanx了解解决方案和解释。然而,我必须说,我发现很难理解到底发生了什么(“&”部分,为什么要更改函数名,为什么要使用scope.&parent
),我的解释不是最好的。我已经更新了,所以我希望它更清晰一点。&
的工作方式相当棘手。如果有帮助,scope.onNodeClickFn=scope.$parent.onNodeClickFn
只需将onNodeClickFn
的副本一直放在当前作用域上(将父作用域上的副本复制到当前嵌套作用域)。感谢您的更新答案,不胜感激。尽管如此,这仍然是一件困难的事情:)@b1r3k这是你的plunker更新了:原来的JSFIDLE似乎不再工作了。onNodeClickFn中的console.log命令不会激发。
<recursive-list-item data-parent="child" data-on-node-click="topFunc(node)" top-func="topFunc"></recursive-list-item> \
<ul data-ng-if="parent.Children.length > 0" data-ng-show="visible"> \
<li ng-repeat="child in parent.Children"> \
<recursive-list-item data-parent="child" data-on-node-click="onNodeClick({param:param})"></recursive-list-item> \
</li> \
</ul>',
on-node-click="onNodeClick(param1,param2)"
onNodeClick({param1: value1, param2:value2})