mini-program-event-store
Version:
A small responsive system suitable for handling data responsive issues in mini program development
256 lines (224 loc) • 7.34 kB
JavaScript
;
class EventBus {
constructor() {
this.eventBus = {};
}
/**
*
* @param {事件名} eventName
* @param {事件回调函数} eventCallback
* @param {绑定this} thisArg
* @returns this
*/
on(eventName, eventCallback, thisArg) {
if (typeof eventName !== "string") {
throw new TypeError("the event name must be string type");
}
if (typeof eventCallback !== "function") {
throw new TypeError("the event callback must be function type");
}
/**
* 将事件命收集起来,比如:
* eventBus= { why: [{eventCallback, thisArg}] }
*/
let handlers = this.eventBus[eventName];
if (!handlers) {
handlers = [];
this.eventBus[eventName] = handlers;
}
handlers.push({
eventCallback,
thisArg,
});
/**
* 返回 this 是为了支持链式调用
* eventBus.on('event1', callback1)
* .on('event2', callback2)
* .once('event3', callback3);
*
*/
return this;
}
once(eventName, eventCallback, thisArg) {
if (typeof eventName !== "string") {
throw new TypeError("the event name must be string type");
}
if (typeof eventCallback !== "function") {
throw new TypeError("the event callback must be function type");
}
// 创建一个新的回调函数 tempCallback,当接收到emit时,传给 原始的 eventCallback
const tempCallback = (...payload) => {
// 先把自己 的回调函数 移除
this.off(eventName, tempCallback);
// 然后执行原始的 eventCallback,将数据传回去
eventCallback.apply(thisArg, payload);
};
return this.on(eventName, tempCallback, thisArg);
}
/**
*
* @param {事件名} eventName
* @param {参数载荷} payload
* @returns this
*
* 在eventBus中查找对应的事件名,如果存在,则执行对应的回调函数
*/
emit(eventName, ...payload) {
if (typeof eventName !== "string") {
throw new TypeError("the event name must be string type");
}
const handlers = this.eventBus[eventName] || [];
handlers.forEach((handler) => {
handler.eventCallback.apply(handler.thisArg, payload);
});
return this;
}
/**
*
* @param {要取消监听的事件名} eventName
* @param {回调函数} eventCallback
*/
off(eventName, eventCallback) {
if (typeof eventName !== "string") {
throw new TypeError("the event name must be string type");
}
if (typeof eventCallback !== "function") {
throw new TypeError("the event callback must be function type");
}
// eventBus= { why: [ {callback1, thisArg}, {callback2, thisArg}], {callback3, thisArg}] }
// 找到对应的 回调函数数组
const handlers = this.eventBus[eventName];
if (handlers && eventCallback) {
const newHandlers = [...handlers];
for (let i = 0; i < newHandlers.length; i++) {
const handler = newHandlers[i];
if (handler.eventCallback === eventCallback) {
// 将取消监听的回调函数 删除
const index = handlers.indexOf(handler);
handlers.splice(index, 1);
}
}
}
if (handlers.length === 0) {
delete this.eventBus[eventName];
}
}
clear() {
this.emitBus = {};
}
// 检查是否存在指定名称的事件
hasEvent(eventName) {
return Object.keys(this.emitBus).includes(eventName);
}
}
function isObject(obj) {
var type = typeof obj;
return type === "object" && !!obj;
}
class EventStore {
constructor(options) {
if (!isObject(options.state)) {
throw new TypeError("the state must be object type");
}
if (options.actions && isObject(options.actions)) {
const values = Object.values(options.actions);
for (const value of values) {
if (typeof value !== "function") {
throw new TypeError("the value of actions must be a function");
}
}
this.actions = options.actions;
}
this.state = options.state;
this._observe(options.state);
this.event = new EventBus();
this.eventV2 = new EventBus();
}
_observe(state) {
const _this = this;
Object.keys(state).forEach((key) => {
let _value = state[key];
Object.defineProperty(state, key, {
get: function () {
return _value;
},
set: function (newValue) {
if (_value === newValue) return;
/**
* 这里没有赋值(state[key] = "newValue"),为什么对应的value值是最新的?
* get 返回的是_value
*/
_value = newValue;
// 用于 onState
_this.event.emit(key, _value);
// 用于 onStates
_this.eventV2.emit(key, { [key]: _value });
},
});
});
}
// 监听 stateKey 的变化
onState(stateKey, stateCallback) {
const keys = Object.keys(this.state);
if (keys.indexOf(stateKey) === -1) {
throw new Error("the state does not contain your key");
}
// 收集依赖
this.event.on(stateKey, stateCallback);
// callback
if (typeof stateCallback !== "function") {
throw new TypeError("the event callback must be function type");
}
// 立即执行回调函数,返回stateKey的值。后面stateKey变化了,执行bus里面的回调就行了
const value = this.state[stateKey];
stateCallback.apply(this.state, [value]);
}
// ["name", "age"] callback1
// ["name", "height"] callback2
// 监听 多个stateKey 的变化
onStates(statekeys, stateCallback) {
const keys = Object.keys(this.state);
const value = {};
for (const theKey of statekeys) {
if (keys.indexOf(theKey) === -1) {
throw new Error("the state does not contain your key");
}
this.eventV2.on(theKey, stateCallback);
value[theKey] = this.state[theKey];
}
stateCallback.apply(this.state, [value]);
}
offStates(stateKeys, stateCallback) {
const keys = Object.keys(this.state);
stateKeys.forEach((theKey) => {
if (keys.indexOf(theKey) === -1) {
throw new Error("the state does not contain your key");
}
this.eventV2.off(theKey, stateCallback);
});
}
offState(stateKey, stateCallback) {
const keys = Object.keys(this.state);
if (keys.indexOf(stateKey) === -1) {
throw new Error("the state does not contain your key");
}
this.event.off(stateKey, stateCallback);
}
// 更改 stateKey 的值
setState(stateKey, stateValue) {
// 触发set -> emit
this.state[stateKey] = stateValue;
}
dispatch(actionName, ...args) {
if (typeof actionName !== "string") {
throw new TypeError("the action name must be string type");
}
if (Object.keys(this.actions).indexOf(actionName) === -1) {
throw new Error("this action name does not exist, please check it");
}
const actionFn = this.actions[actionName];
actionFn.apply(this, [this.state, ...args]);
}
}
exports.EventBus = EventBus;
exports.EventStore = EventStore;