Vue_Cocos/public/static/js/EventBus.js
2022-08-01 17:30:55 +08:00

180 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 实现发布-订阅模式下的消息传输机制,支持命名空间与离线事件
* @param {string} [key] 事件的名称
* @param {function} [fn] 事件的回调
* @param {string} [last] 是否只执行最后一次绑定的消息 last ==“last”时只执行最后一次绑定的消息否则执行之前所有绑定的消息
*
* @example
* 1.常规
* eventBus.on('click',function(a){
* console.log(a) // 输出 :1
* })
* eventBus.emit('click',1)
*
* 2. 先发布后订阅
* eventBus.emit('click',1)
* eventBus.on('click',function(a){
* console.log(a) // 输出 :1
* })
*
* 3.使用命名空间
* eventBus.create('namespace1').on('click',function(a){
* console.log(a) // 输出 :1
* })
* eventBus.create('namespace1').emit('click',1)
*
* auth by guoqiang
* 注意:支持离线事件可能会带来一些副作用,比如意外的某个页面发布了某个消息,这时如果另一个订阅了这个消息,这个消息的回调会立即执行,而且大多请况下,回调的参数会出问题。在逻辑没理清之前不建议先发布再订阅
* 注意:支持离线事件可能会带来一些副作用,比如意外的某个页面发布了某个消息,这时如果另一个订阅了这个消息,这个消息的回调会立即执行,而且大多请况下,回调的参数会出问题。在逻辑没理清之前不建议先发布再订阅
* 注意:支持离线事件可能会带来一些副作用,比如意外的某个页面发布了某个消息,这时如果另一个订阅了这个消息,这个消息的回调会立即执行,而且大多请况下,回调的参数会出问题。在逻辑没理清之前不建议先发布再订阅
*/
(function(window, undefined) {
var _subscribe = null,
_publish = null,
_unsubscribe = null,
_shift = Array.prototype.shift, // 删除数组的第一个 元素,并返回这个元素
_unshift = Array.prototype.unshift, // 在数组的开头添加一个或者多个元素并返回数组新的length值
namespaceCache = {},
_create = null,
each = function(ary, fn) {
var ret = null;
for (var i = 0, len = ary.length; i < len; i++) {
var n = ary[i];
ret = fn.call(n, i, n);
}
return ret;
};
// 订阅消息名称为:'+key+'
_subscribe = function(key, fn, cache) {
if (!cache[key]) {
cache[key] = [];
}
cache[key].push(fn);
};
// 取消订阅(取消全部或者指定消息)
_unsubscribe = function(key, cache, fn) {
if (cache[key]) {
if (fn) {
for (var i = cache[key].length; i >= 0; i--) {
if (cache[key][i] === fn) {
cache[key].splice(i, 1);
}
}
} else {
cache[key] = [];
}
} else if (!key) {
for (var key in cache) {
delete cache[key];
}
} else {
console.log("不存在该消息的监听:" + key);
}
};
// 发布消息
_publish = function() {
var cache = _shift.call(arguments),
key = _shift.call(arguments),
args = arguments,
_self = this,
ret = null,
stack = cache[key];
if (!stack || !stack.length) {
return;
}
return each(stack, function() {
return this.apply(_self, args);
});
};
// 创建命名空间
_create = function(namespace) {
var namespace = namespace || "default";
var cache = {},
offlineStack = {}, // 离线事件,用于先发布后订阅,只执行一次
ret = {
on: function(key, fn, last) {
_subscribe(key, fn, cache);
if (!offlineStack[key]) {
offlineStack[key] = null;
return;
}
if (last === "last") {
// 指定执行离线队列的最后一个函数,执行完成之后删除
offlineStack[key].length && offlineStack[key].pop()(); // [].pop => 删除一个数组中的最后的一个元素,并且返回这个元素
} else {
each(offlineStack[key], function() {
this();
});
}
offlineStack[key] = null;
},
one: function(key, fn, last) {
_unsubscribe(key, cache);
this.on(key, fn, last);
},
off: function(key, fn) {
_unsubscribe(key, cache, fn);
},
emit: function() {
var fn = null,
args = null,
key = _shift.call(arguments),
_self = this;
_unshift.call(arguments, cache, key);
args = arguments;
fn = function() {
return _publish.apply(_self, args);
};
if (offlineStack && offlineStack[key] === undefined) {
offlineStack[key] = [];
return offlineStack[key].push(fn);
}
return fn();
}
};
return namespace
? namespaceCache[namespace]
? namespaceCache[namespace]
: (namespaceCache[namespace] = ret)
: ret;
};
window.eventBus = {
create: _create, // 创建命名空间
one: function(key, fn, last) {
// 订阅消息,只能单一对象订阅
var namespace = "default";
var pubsub = this.create(namespace);
pubsub.one(key, fn, last);
},
on: function(key, fn, last) {
// 订阅消息,可多对象同时订阅
var namespace = "default";
var pubsub = this.create(namespace);
pubsub.on(key, fn, last);
},
off: function(key, fn, namespace) {
// 取消订阅,(取消全部或指定消息)
namespace = "default";
var pubsub = this.create(namespace);
console.trace("");
pubsub.off(key, fn);
},
emit: function(key, fn) {
// 发布消息
var namespace = "default";
var pubsub = this.create(namespace);
pubsub.emit.apply(this, arguments);
}
};
})(window, undefined);