我正在用 Angular 构建一个类似咆哮的 UI。我想将其公开为工厂(或服务),以使其在我的 Controller 中可用。调用 Growl.add 将导致 DOM 发生变化,所以看起来我应该有一个指令来处理这个问题,而不是在工厂中直接进行 DOM 操作。假设工厂指令组合是最佳选择(如果这不是一个好的假设,请纠正我),问题是:
工厂和指令之间如何最好地沟通?
具体来说,如何最好地将消息从工厂发送到指令?其他问题很好地涵盖了通过一次性回调以另一种方式发送信息。
请参阅下面的工作示例。我怀疑有更好的方法..
作为引用,我尝试过其他选项:
A) 让指令监视服务,例如
$scope.$watch(function(){
growl.someFunctionThatGetsNewData()},
function(newValue){
//update scope
})
但这意味着 someFunctionThatGetsNewData 在每个摘要周期中都会被调用,这看起来很浪费,因为我们知道数据只会在 Growl.add 上更改
B) 通过 Routescope 或 dom/window 上的事件绑定(bind)发送“事件”。看起来没有棱 Angular
由于这两个选项看起来都不太好,所以我使用了下面的一个,但它仍然感觉很糟糕。 register
函数意味着指令和工厂紧密耦合。但话又说回来,从使用的 Angular 来看,它们是紧密结合在一起的——一个没有另一个就不好。
理想的解决方案似乎涉及声明一个工厂(或服务),该工厂(或服务)在其声明(可能还有功能范围)中包含该指令,以便它公开一个公共(public)接口(interface)。拥有两个完全相互依赖且在接口(interface)中紧密耦合的单独的公开声明的组件似乎很糟糕。
工作示例 - 但必须有更好的方法..
vpModule.directive('vpGrowl',['$timeout', 'growl', function ($timeout, growl) {
return {
template: '<div>[[msg]]</div.',
link: function($scope, elm, attrs) {
growl.register(function(){
$scope.msg = growl.msg;
});
$scope.msg = growl.msg;
}
};
}]);
vpModule.factory('growl', ['$rootScope', '$sce', function($rootScope, $sce) {
var growl = {};
growl.msg = '';
var updateCallback = function(){};
growl.add = function(msg){
growl.msg = msg;
updateCallback();
};
growl.register = function(callback){
updateCallback = callback;
};
return growl;
}]);
最佳答案
我会让你的咆哮服务决定显示什么,而不是指令。因此,该服务会处理任何计时器、状态等来决定何时隐藏/显示消息。然后,该服务公开该指令简单绑定(bind)到的消息集合。
该指令可以注入(inject)服务并将其简单地放置在范围内,然后将 ng-repeat 绑定(bind)到服务的集合。是的,这确实涉及到 watch ,但您真的不需要像这样担心单个 watch 的性能。
link: function(scope, elm, attrs) {
scope.growl = growl; // where 'growl' is the injected service
}
然后在指令模板中:
<div ng-repeat="msg in growl.messages">
...
</div>
关于javascript - 如何构建操纵 DOM 的 Angular 因子/服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25920694/