除了发出事件或将指令包装到父控制器中之外,还有另一种选择(顺便说一句,这些选项没有错)。另一种选择是拥有一个通用服务/工厂,您可以在其中注册任意指令控制器,然后在其他相关或非相关指令中使用这些注册的控制器。
下面有一个服务directiveCommunicator
,你可以在其中获取、设置和取消设置指令控制器(如果需要,你可以使用工厂,这只是我使用服务的偏好)。然后,我们有另外 2 个指令,称为foo
and bar
,这些foo
指令注册了要使用的控制器,而该控制器又被bar
指令使用。请注意,foo
和bar
指令与父/子无关
// Service used to register/use any arbitrary controller
app.service('directiveCommunicator',
function()
{
var _controllers = {};
this.get =
function(id)
{
if (!(id in _controllers)) {
return null;
}
return _controllers[id];
};
this.set =
function(id, controller)
{
_controllers[id] = controller;
};
this.unset =
function(id)
{
if (!(id in _controllers)) {
return;
}
delete _controllers[i];
}
}
);
app.directive('foo',
[
'directiveCommunicator',
function(directiveCommunicator)
{
return {
'restrict': 'A',
'scope':
{
'colour': '='
},
'controller':
function($scope)
{
// We register out controller with a unique ID so we can use it in other directives
directiveCommunicator.set('colourBox', this);
// We also unregister it once we get destroyed, otherwise we'll be leaking memory
$scope.$on('$destroy',
function()
{
directiveCommunicator.unset('colourBox');
}
);
this.changeColour =
function(colour)
{
$scope.$apply(
function()
{
$scope._colour = colour;
}
);
}
},
'link':
function($scope, $element, $attr)
{
$scope._colour = $attr.colour;
$scope.$watch('_colour',
function()
{
$element.attr('class', $scope._colour);
}
);
}
}
}
]
);
app.directive('bar',
[
'directiveCommunicator',
function(directiveCommunicator)
{
return {
'restrict': 'A',
'scope':
{
'colour': '='
},
'link':
function($scope, $element, $attr)
{
$element.text($attr.colour);
$element.bind('click',
function()
{
// We get the registered controller and call the 'changeColour' method on it
var ctrl = directiveCommunicator.get('colourBox');
ctrl.changeColour($attr.colour);
}
);
}
}
}
]
);
我做了一个小Plunker演示来查看foo
和bar
操作。该foo
指令只是一个小方形 div,您可以在其中更改关联控制器中的背景。bar
是另一个不相关的指令,它将调用foo
的控制器方法changeColour
并根据提供的属性更改颜色。
尚未在生产中使用此设置,您还需要处理注销控制器,但应该可以。您还可以在方法中使用第三个参数directiveCommunicator.set
作为控制器的范围,该方法将自动添加到 $destroy/unregister 设置中,因此不必再directiveCommunicator.unset
调用