Javascript 如何在服务中封装单个事件和临时事件?
我试图将事件封装在服务中,以便在控制器的作用域被破坏时实现订阅/取消订阅侦听器的机制。这是因为我一直以以下方式使用Javascript 如何在服务中封装单个事件和临时事件?,javascript,angularjs,angularjs-scope,dom-events,Javascript,Angularjs,Angularjs Scope,Dom Events,我试图将事件封装在服务中,以便在控制器的作用域被破坏时实现订阅/取消订阅侦听器的机制。这是因为我一直以以下方式使用rootScope.$on: if(!$rootScope.$$listeners['event']) { $rootScope.$on('event', function(ev, data){ // do some... }); } 或 所以我只需要这个事件的一个监听器,我需要在控制器不再处于活动状态时删除现有的监听器,因为我之前注册的函数仍在被触
rootScope.$on
:
if(!$rootScope.$$listeners['event']) {
$rootScope.$on('event', function(ev, data){
// do some...
});
}
或
所以我只需要这个事件的一个监听器,我需要在控制器不再处于活动状态时删除现有的监听器,因为我之前注册的函数仍在被触发
因此,我需要在我的控制器上实现一个$destroy
事件侦听器,以便在范围被销毁时销毁侦听器,但我不希望每次创建事件时都执行该代码。
这就是为什么我想创建一个服务,在其中我将封装事件
angular.module('core').factory('event', [
function() {
var service = {};
service.events = {};
service.on = function(scope, eventId, callback) {
scope.$on('$destroy', function(ev, other){
//unsubscribe
});
service.events[eventId] = callback;
// scope = null; I guess ?
};
service.emit = function(eventId, data){
if (service.events[eventId])
service.events[eventId](data);
else
return new Error('The event is not subscribed');
};
return service;
}
]);
这可以使用$rootScope而不是我自己的方法来完成,但要封装$rootScope的$on
和$emit
,但最后我会遇到同样的问题
以下是我的问题:
$$destromed
的含义是什么?如果这是真的,意味着angularJS没有对实例的内部引用您试图完成的基本上是一个事件总线
您还很好地描述了当前实现的错误。 解决这个问题的另一种方法是用您的总线(或任何其他事件总线)装饰$rootScope。以下是如何:
app.config(function ($provide) {
$provide.decorator('$rootScope', ['$delegate', '$$bus', function ($delegate, $$bus) {
Object.defineProperty($delegate.constructor.prototype, '$bus', {
get: function () {
var self = this;
return {
subscribe: function () {
var sub = $$bus.subscribe.apply($$bus, arguments);
self.$on('$destroy',
function () {
console.log("unsubscribe!");
sub.unsubscribe();
});
},
publish: $$bus.publish
};
},
enumerable: false
});
return $delegate;
}]);
});
考虑以下$$总线实现(为了简单起见保持基本):
现在您所要做的就是订阅或发布事件。取消订阅将自动进行(当$scope被销毁时):
然后发布一个事件:
$scope.$bus.publish('test', {name: "publishing event!"});
重要的一点是,事件本身订阅到每个单独的$scope,而不是$rootScope。这就是您“知道”要发布哪个$scope的方式
我想这回答了你的问题。考虑到这一点,您显然可以使该机制更加复杂(例如,当视图路由时释放控制器事件侦听器,仅自动取消订阅某些事件,等等)。
祝你好运
**此解决方案采用了使用不同总线框架的形式(除此之外是相同的)。我在所有项目中使用的“!!!”@dandavis==”是什么意思,所以我正在使用!!为了铸造虚假的价值观,我又一次匆忙地否定了。。我知道。。只是好的,谢谢!这正是我需要的,这个解决方案非常完美。
app.factory('$$bus', function () {
var api = {};
var events = {};
api.subscribe = function (event) {
if (!events.hasOwnProperty(event.name)) {
events[event.name] = [event];
} else {
events[event.name].push(event);
}
return {
unsubscribe: function () {
api.unsubscribe(event);
}
}
};
api.publish = function (eventName, data) {
if (events.hasOwnProperty(eventName)) {
console.log(eventName);
angular.forEach(events[eventName], function (subscriber) {
subscriber.callback.call(this, data);
});
}
};
api.unsubscribe = function (event) {
if (events.hasOwnProperty(event.name)) {
events[event.name].splice(events[event.name].indexOf(event), 1);
if (events[event.name].length == 0) {
delete events[event.name];
}
}
};
return api;
});
$scope.$bus.subscribe({
name: 'test', callback: function (data) {
console.log(data);
}
});
$scope.$bus.publish('test', {name: "publishing event!"});