Ben*_*ink 5 angularjs angularjs-directive angularjs-scope
我正在尝试在父指令和它的嵌套子指令之间进行通信,反之亦然.我已经设法通过使用$ broadcast和$ emit来实现这一点,但是因为我在指令中传递了一些参数,我必须在我的指令上创建隔离范围,所以为了$ broadcast/$ emit来我必须在父作用域(范围.$ parent.$ broadcast)上播放'up a level'.现在,广播不再仅仅是针对嵌套子节点,而是针对同级别的所有指令,这是我不想要的.我创建了一个plunker显示问题,在这里.我需要的是当按下其中一个按钮时,只有child指令接收广播消息,反之亦然.我错过了什么,或者在使用隔离范围时这是不可能的?
在我的HTML中:
<body ng-app="myApp">
<directive1 data-title="Click me to change name">
<directive2 data-name="John Smith"></directive2>
</directive1>
<directive1 data-title="Click me to change this other name">
<directive2 data-name="Gordon Freeman"></directive2>
</directive1>
</body>
Run Code Online (Sandbox Code Playgroud)
指令1:
<div>
<button ng-click="changeName()">{{title}}</button>
<div ng-transclude></div>
</div>
Run Code Online (Sandbox Code Playgroud)
指令2:
<div>
<h2>{{name}}</h2>
</div>
Run Code Online (Sandbox Code Playgroud)
我的指示:
myApp.directive('directive1', function(){
return {
restrict: 'E',
replace: true,
templateUrl: 'Directive1.html',
transclude: true,
scope: {
title: '@'
},
link: function(scope, elem){
scope.changeName = function() {
scope.$parent.$broadcast('ChangeName');
};
scope.$parent.$on('NameChanged', function(event, args){
scope.title = 'Name changed to ' + args;
});
}
}
});
myApp.directive('directive2', function(){
return {
restrict: 'E',
replace: true,
templateUrl: 'Directive2.html',
scope: {
name: '@'
},
link: function(scope, elem){
scope.$on('ChangeName', function(event, args){
scope.name = 'Adam West';
scope.$emit('NameChanged', 'Adam West');
});
}
}
});
Run Code Online (Sandbox Code Playgroud)
指令之间的通信主要有 5 种方式:
1)公共服务。
这对您来说不是一个好的解决方案,因为服务始终是单例的,并且您希望拥有多个唯一的指令。如果您在服务中维护了父级和子级的字典,并管理将调用路由到正确关联的父级/子级,那么您只能使用该服务,这与使用事件时遇到的问题相同。
2)事件。
如果您无法通过从正确的节点进行广播来将事件限制在 DOM/树的正确部分,则必须向事件添加唯一标识符。在这种情况下,如果您从根进行广播和/或多个子级正在接收消息,请为每个父级/子级提供唯一标识符并将其添加到emit/broadcast/on。这不是一个很好的解决方案,但它会起作用。
3) 单向绑定。
隔离作用域中的“&”绑定允许您将父函数传递给子函数。然后,子级可以在父级作用域上调用这些函数,以通知父级发生更改。这对于孩子与家长的沟通非常有用,但不会适得其反。您可以将此解决方案与从父级广播事件以与子级进行通信相结合。
4)双向绑定。
有时,您可以在隔离范围上使用属性来在父子之间传递信息或标志。这在您的示例中不起作用,因为父母对他的孩子一无所知,因为孩子是通过嵌入注入的。
5)require父控制器。
指令可以使用该require属性来指定另一个指令需要作为父级或同一元素存在。您不能要求兄弟指令。所需的指令必须定义控制器。然后控制器被传递到链接(或编译)函数,您可以调用控制器上的函数。这可用于允许指令之间的通信。在您的示例中,如果指令2需要指令1,您可以设置类似于addChild()控制器的功能。然后,子级(directive2)会将自身添加到父级,当调用changeName时,父级可以更新/调用所有子级。
myApp.directive('directive1', function(){
return {
// ...
controller: function($scope) {
$scope.children = [];
this.addChild = function(child) {
$scope.children.push(child);
}
},
link: function(scope, elem){
scope.changeName = function() {
_.each(scope.children, function(child) {
child.setName('Adam West');
};
};
},
}
});
myApp.directive('directive2', function(){
return {
// ...
require: "^directive1", // require directive1 as a parent or on same element
link: function(scope, elem, attributes, directive1Controller){
child = {
setName: function(name) {
scope.name = name;
},
};
directive1Controller.addChild(child);
}
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2396 次 |
| 最近记录: |