Online Use | English | 更新日志 | 反馈错误/缺漏 | Gitee
- typescript 编写
- 多端支持
- 自定义事件顺序、多种触发模式
- 全局拦截机制
- 体积小巧,简单易用
- 支持创建模块,避免事件冲突
npm i tc-event
import event from 'tc-event';
event.regist('myEvent', (data) => {
console.log('emited!', data);
})
event.emit('myEvent', 'Aha!');
<script src="https://cdn.jsdelivr.net/npm/tc-event/tc-event.min.js"></script>
<script>
TEvent.regist('myEvent', function (data) {
console.log('emited!', data);
})
TEvent.emit('myEvent', 'Aha!');
</script>
详情请参考 index.d.ts
export interface IEventEmitter {
removed: boolean;
interceptor: IEventInterceptor;
name: string;
getEventNames(): string[]; // 事件枚举
getEvent(): IEventJson<CEvent>;
getEvent(name: TEventName): CEvent;
emit(name: TEventName, data?: any): boolean; // 触发事件
onEmit(fn: IOnInterceptorEmit): void;
regist: IRegistMethod;
registObject(options: IEventRegistOption & {eventName: TEventName}): IListenerItem;
onRegist(fn: IOnInterceptorRegist): void;
checkEvent(name: TEventName): boolean; // 检查是否存在事件
remove: IRemoveMethod;
clear(name?: TEventName | TEventName[]): void;
order(name: TEventName): number;
registNotImmediate(name: TEventName, listener: IEventListener): IListenerItem;
registNotImmediateOnce(name: TEventName, listener: IEventListener): IListenerItem;
registOnce(name: TEventName, listener: IEventListener): IListenerItem;
registSingle(name: TEventName, listener: IEventListener): IListenerItem;
}
export interface IEventStatic extends IEventEmitter {
version: string;
createModule (name: TModuleName): IEventEmitter;
getModule (): IEventJson<IEventEmitter>;
getModule (name: TModuleName): IEventEmitter;
removeModule(name: TModuleName): void;
clearModule(): void;
EventEmitter: typeof EventEmitter;
}
判断事件是否存在
const eventName = 'test-checkEvent';
const result = [];
result.push(event.checkEvent(eventName));
event.regist(eventName, () => {});
result.push(event.checkEvent(eventName));
event.emit(eventName);
result.push(event.checkEvent(eventName));
event.clear(eventName);
result.push(event.checkEvent(eventName));
event.regist(eventName, () => {});
result.push(event.checkEvent(eventName));
event.clear();
result.push(event.checkEvent(eventName));
console.log(result);
// [false, true, true, false, true, false]
清除单个或所有事件
const eventName = 'test-clear';
const result = [];
event.regist(eventName, () => {
result.push(1);
});
event.emit(eventName);
event.clear(eventName);
event.emit(eventName);
event.regist(eventName, {
immediate: false,
listener: () => {
result.push(2);
}
});
event.emit(eventName);
event.clear();
event.emit(eventName);
console.log(result);
// [1, 2]
immediate 参数表示注册事件时,如果该事件已经被触发过,是否需要立即触发当前的事件
默认值为 true
const eventName = 'test-immediate';
const result = [];
event.emit(eventName);
event.regist(eventName, () => {
result.push(1);
});
event.regist(eventName, {
immediate: true,
listener () { result.push(2);}
});
event.regist(eventName, {
immediate: false,
listener () {result.push(3);}
});
console.log(result);
// [1, 2]
index 参数表示注册事件时,希望插入的位置
const eventName = 'test-order';
const result = [];
event.regist(eventName, () => {
result.push(1); // 1
});
event.regist(eventName, () => {
result.push(2); // 1 2
});
event.regist(eventName, () => {
result.push(3); // 1 2 3
});
event.regist(eventName, () => {
result.push(4); // 1 2 3 4
});
event.regist(eventName, {
index: 0, // 5 1 2 3 4
listener () {result.push(5);}
});
event.regist(eventName, {
index: 2, // 5 1 6 2 3 4
listener () {result.push(6);}
});
event.regist(eventName, {
index: 1, // 5 7 1 6 2 3 4
listener () {result.push(7);}
});
event.regist(eventName, {
index: 100, // 5 7 1 6 2 3 4 8
listener () {result.push(8);}
});
event.regist(eventName, {
index: -3, // 9 5 7 1 6 2 3 4 8
listener () {result.push(9);}
});
event.emit(eventName);
console.log(result);
// [9, 5, 7, 1, 6, 2, 3, 4, 8]
全局拦截器,支持 onRegist 和 onEmit
const eventName1 = 'test-interceptor1';
const eventName2 = 'test-interceptor2';
const result = [];
event.onRegist(({name, item}) => {
result.push(`onRegist: ${name}`);
});
event.onEmit(({name, item, data, firstEmit}) => {
result.push(`onEmit: ${name} ${data} ${firstEmit}`);
});
event.regist(eventName1, () => {});
event.regist(eventName2, () => {});
event.emit(eventName1, `${eventName1} data`);
event.emit(eventName2, `${eventName2} data`);
event.emit(eventName2, `${eventName2} data2`);
console.log(result);
/*
[
'onRegist: test-interceptor1',
'onRegist: test-interceptor2',
'onEmit: test-interceptor1 test-interceptor1 data true',
'onEmit: test-interceptor2 test-interceptor2 data true',
'onEmit: test-interceptor2 test-interceptor2 data2 false'
]
*/
once 参数 是否只触发依次
const eventName = 'test-once';
const result = [];
event.regist(eventName, () => {
result.push(1);
});
event.regist(eventName, {
once: true,
listener () { result.push(2);}
});
event.regist(eventName, {
once: false,
listener () {result.push(3);}
});
event.emit(eventName);
event.emit(eventName);
console.log(result);
// [1, 2, 3, 1, 3]
times 参数 监听触发的次数
const eventName = 'test-times';
const result = [];
event.regist(eventName, {
times: 1,
listener () { result.push(1);}
});
event.regist(eventName, {
times: 2,
listener () { result.push(2);}
});
event.regist(eventName, {
times: 3,
listener () { result.push(3);}
});
event.emit(eventName);
event.emit(eventName);
event.emit(eventName);
event.emit(eventName);
// [1, 2, 3, 2, 3, 3]
控制插入事件的序号(和 index参数有区别)
const eventName = 'test-order';
const result = [];
event.regist(eventName, () => {
result.push(1); // 1
});
event.regist(eventName, () => {
result.push(2); // 1 2
});
event.regist(eventName, {
order: 0, // 0 1 2
listener () {result.push(3);}
});
event.regist(eventName, {
order: 1, // 0 1 *1 2
listener () {result.push(4);}
});
event.regist(eventName, {
order: 1, // 0 1 *1 **1 2
listener () {result.push(5);}
});
event.regist(eventName, {
order: 1, // 0 ***1 1 *1 **1 2
orderBefore: true,
listener () {result.push(6);}
});
event.regist(eventName, {
order: 10, // 0 ***1 1 *1 **1 2 10
listener () {result.push(7);}
});
event.regist(eventName, () => { // 0 ***1 1 *1 **1 2 3 10
result.push(8);
});
event.emit(eventName);
console.log(result);
单例监听模式,对某个事件名启用 single 参数会覆盖之前该事件的所有监听函数
且之后该事件无需再带上 single 参数
启用single参数时, index order orderBefore 参数无效
const eventName = 'test-single';
const result = [];
event.regist(eventName, () => {
result.push(1);
});
event.emit(eventName);
// 测试覆盖旧方法
event.regist(eventName, {
single: true,
immediate: false,
listener: () => {
result.push(2);
}
});
event.emit(eventName);
event.clear(eventName);
event.regist(eventName, {
single: true,
listener () { result.push(3);}
});
event.regist(eventName, {
single: true,
listener () { result.push(4);}
});
event.emit(eventName);
// 测试single参数缓存
event.regist(eventName, {
immediate: false,
listener () { result.push(5);}
});
event.emit(eventName);
console.log(result);
// [1, 2, 4, 5]
name 参数用来给一个监听增加一个参数
默认值为 eventName + id
const eventName = 'test-name';
const item1 = event.regist(eventName, () => {
});
const item2 = event.regist(eventName, {
name: 'listener-name',
listener () {}
});
// item1.name === 'test-name-1'
// item2.name === 'listener-name'
head参数用于将监听添加到事件头部
const eventName = 'test-head';
const result = [];
event.regist(eventName, () => {
result.push(1);
});
event.regist(eventName, {
order: -1,
listener () {result.push(2);}
});
event.regist(eventName, {
index: -1,
listener () {result.push(3);}
});
event.regist(eventName, {
head: true,
listener () {result.push(4);}
});
event.regist(eventName, {
head: true,
listener () {result.push(5);}
});
event.emit(eventName);
// result: [5, 4, 3, 2, 1]
tail参数用于将监听添加到事件尾部
const eventName = 'test-tail';
const result = [];
event.regist(eventName, () => {
result.push(1);
});
event.regist(eventName, {
order: 100,
listener () {result.push(2);}
});
event.regist(eventName, {
index: 100,
listener () {result.push(3);}
});
event.regist(eventName, {
listener () {result.push(4);}
});
event.regist(eventName, {
tail: true,
listener () {result.push(5);}
});
event.regist(eventName, {
tail: true,
listener () {result.push(6);}
});
event.emit(eventName);
// result: [1, 4, 2, 3, 5, 6]
获取某个监听的序号
const eventName = 'test-order-fn';
const result = [];
event.regist(eventName, () => {
result.push(1);
});
event.regist(eventName, () => {
result.push(2);
});
const e1 = event.regist(eventName, () => {
result.push(3);
});
const e2 = event.regist(eventName, {
order: 1,
listener () { result.push(4);}
});
event.regist(eventName, () => {
result.push(5);
});
event.emit(eventName);
console.log([result, event.order(eventName), e1.order, e2.order]);
// [[1, 4, 2, 3, 5], 4, 3, 1
移除事件监听
const eventName = 'test-remove';
const result = [];
const l4 = () => { result.push(4); };
const l5 = () => { result.push(5); };
const l6 = () => { result.push(6); };
const l7 = () => { result.push(7); };
event.regist(eventName, () => {
result.push(1);
});
event.regist(eventName, () => {
result.push(2);
});
event.regist(eventName, () => {
result.push(3);
event.remove(eventName, l4, true);
event.remove(eventName, l5);
event.regist(eventName, l7);
});
event.regist(eventName, l4);
event.regist(eventName, l5);
event.regist(eventName, l6);
event.remove(eventName, l6);
event.emit(eventName);
event.emit(eventName);
console.log(result);
// [1, 2, 3, 7, 5, 1, 2, 3, 7, 7]
event.registNotImmediate('xxx', ()=>{})
// 等价于
event.regist('xxx', {
immediate: false,
listener: ()=>{}
})
event.registOnce('xxx', ()=>{})
// 等价于
event.regist('xxx', {
once: true,
listener: ()=>{}
})
event.registNotImmediateOnce('xxx', ()=>{})
// 等价于
event.regist('xxx', {
immediate: false,
once: true,
listener: ()=>{}
})
event.registSingle('xxx', ()=>{})
// 等价于
event.regist('xxx', {
single: true,
listener: ()=>{}
})
监听函数第二个参数是一个json,包含有三个属性
- firstEmit 表示该监听是否是首次触发
- remove 是移除当前监听的方法
- clear 是移除当前事件的方法
- item 是当前的监听对象
event.regist('xxx', (data, {firstEmit, item, remove, clear})=>{
})
regist函数当指传入事件名时会启用链式调用
所有参数都可通过链式调用,所有api都是可选的,最后需要通过 listen 方法触发监听
event.regist('xxx')
.index(1)
.order(1)
.orderBefore()
.notImmediate()
.single()
.once()
.times(1)
.listener()
.name('xxx')
.head()
.tail()
.listen();
声明文件如下
interface IEventLink {
single: (single: boolean) => IEventLink;
notImmediate: (immediate: boolean) => IEventLink;
once: (once: boolean) => IEventLink;
index: (index: number) => IEventLink;
order: (order: number) => IEventLink;
orderBefore: (orderBefore: boolean) => IEventLink;
listener: (listener: IEventListener) => IEventLink;
name: (name: string) => IEventLink;
head: () => IEventLink;
tail: ()=> IEventLink;
times: (times: number)=> IEventLink;
listen: (listener?: IEventListener) => IListenerItem;
}
- createModule
const result = [];
const name = 'module_event';
const moduleA = event.createModule('A');
const moduleB = event.createModule('B');
moduleA.regist(name, data => {result.push('A' + data);});
moduleB.regist(name, data => {result.push('B' + data);});
moduleA.emit(name, 1);
moduleA.emit(name, 2);
console.log(result);
- getModule
event.createModule('A');
event.createModule('B');
console.log([
event.getModule('A').moduleName,
event.getModule('B').moduleName,
]);