mustard-app
Version:
个人前端微应用建设中。。。
142 lines (130 loc) • 5.14 kB
text/typescript
import { IAppStatus, IAppStatusCN, MustardName } from '../typings';
import { isFunction } from '../utils/tools';
export type EventName = MustardName; // 用于区分子应用
export type BindMethod = string;
export type TCallback = (value: unknown, oldValue:unknown, source:MustardName) => void;
export type TLifeCallback = (key: MustardName) => void;
export type TDataChangeCallback = (key: MustardName, data:unknown) => void;
type EventGlobalLifeKey = `globalLife_${IAppStatusCN}`; // 全局生命周期key
type EventGlobalDataChangeKey = 'globalDataChange'; // 全局prop修改key
type EventDataKey = `data_${EventName}`; // prop注入key
type EventDataChangeKey = `dataChange_${EventName}`; // prop修改key
type EventLifeKey = `life_${EventName}_${IAppStatusCN}`; // 生命周期key
type EventBindKey = `bind_${EventName}_${BindMethod}`; // 自定义事件key
export type EventKey = |EventDataKey
|EventDataChangeKey
|EventLifeKey
|EventBindKey
|EventGlobalLifeKey
|EventGlobalDataChangeKey;
export interface EventValue {
data: unknown, // 订阅的数据
sourceOfData: MustardName, // 数据的来源
assignment: boolean, // 是否已经赋值过
callbacks: Set<TCallback>,
repeatSend: WeakSet<TCallback>, // 多次dispatch相同的data,只有第一次生效, 用于去重
}
// 发布订阅系统中心
export class EventCenter {
eventList : Map<EventKey, EventValue> = new Map();
/**
* 初始化
* @param name 事件名
* @param options 事件配置
*/
private initEvent (name:EventKey, options:Partial<EventValue> = {}) {
this.eventList.set(name, {
data: undefined,
sourceOfData: undefined,
assignment: false,
callbacks: new Set(),
repeatSend: new WeakSet(),
...options
});
}
/**
* 订阅事件
* @param name 事件名
* @param fn 事件
* @param param2.immediately 是否立即执行(对应消息dispatch过)
* @param param2.repeatSend 多次dispatch相同的data,只有第一次生效
*/
on (name:EventKey, fn: TCallback, { immediately, repeatSend }:{immediately?: boolean, repeatSend?: boolean} = {}) {
if(!isFunction(fn)) {
return;
}
const events = this.eventList.get(name);
if(!events) {
this.initEvent(name, {
callbacks: new Set([fn]),
repeatSend: new WeakSet(repeatSend ? [fn] : [])
});
}else{
events.callbacks.add(fn);
repeatSend && events.repeatSend.add(fn);
immediately && events.assignment && fn(events.data, undefined, events.sourceOfData);
}
}
/**
* 注销订阅事件
* @param name 事件名
* @param fn 事件 不传递全部清空
*/
off (name:EventKey, fn?: TCallback) {
const events = this.eventList.get(name);
if(events) {
fn ? events.callbacks.delete(fn) : events.callbacks.clear();
}
}
/**
* 发布消息
* @param name 事件名
* @param source 那个应用发送的消息
* @param data 数据
*/
dispatch (name:EventKey, source: MustardName, data?:unknown) {
const events = this.eventList.get(name);
const isSameData = events?.data === data;
if(events) {
const oldData = events.data;
events.assignment = true;
for (const callback of events.callbacks) {
// 存在且值等于上一次不执行,其他的都执行
if(!(events.repeatSend.has(callback) && isSameData)) {
callback(data, oldData, source);
}
}
events.data = data;
events.assignment = true;
events.sourceOfData = source;
}else{
this.initEvent(name, {
data: data,
sourceOfData: source,
assignment: true,
callbacks: new Set([])
});
}
}
}
export function getEventGlobalLifeKeyByValue (value: IAppStatusCN):EventGlobalLifeKey {
return `globalLife_${value}`;
}
export function getEventGlobalDataChangeKey ():EventGlobalDataChangeKey {
return 'globalDataChange';
}
export function getEventDataKey (name: EventName):EventDataKey {
return `data_${name}`;
}
export function getEventDataChangeKey (name: EventName):EventDataChangeKey {
return `dataChange_${name}`;
}
export function getEventLifeKeyByKey (name: EventName, key: IAppStatusCN):EventLifeKey {
return `life_${name}_${key}`;
}
export function getEventLifeKeyByValue (name: EventName, value: IAppStatus):EventLifeKey {
return `life_${name}_${IAppStatus[value]}` as EventLifeKey;
}
export function getEventBindKey (name: EventName, method: BindMethod):EventBindKey {
return `bind_${name}_${method}`;
}