事件机制

事件机制的核心就是发布-订阅模式。维护一个对象,对象的 key 存的是事件 type,对应的 value 为触发相应 type 的回调函数,即 listeners,然后 trigger 时遍历通知,即 forEach 进行回调执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class EventTarget {
constructor() {
this.listener = [];
}

// 监听事件
on(type, callback) {
// 如果是第一次监听该事件,则初始化数组
if (!this.listeners[type]) this.listeners[type] = [];
this.listeners[type].push(callback);
}

// 只监听一次
once(type, callback) {
if (!this.listeners[type]) this.listeners[type] = [];
// once 只触发一次,触发后 off 即可 回调函数加上标识
callback._once = true;
this.listeners[type].push(callback);
}

// 取消监听
off(type, callback) {
const listeners = this.listeners[type];
if (Array.isArray(listeners)) {
// filter 返回新的数组,会每次对 this.listeners[type] 分配新的空间
// this.listeners[type] = listeners.filter(l => l !== callback);
// 根据 type 取消对应的回调
const index = listeners.indexOf(callback);
// 用 splice 要好些,直接操作原数组
this.listeners[type].splice(index, 1);
// 如果回调为空,删除对该事件的监听
if (this.listeners[type].length === 0) delete this.listeners[type];
}
}

// 执行 扳机社
trigger(event) {
// type 为必传属性
const { type } = event;
if (!type) throw new Error('没有要触发的事件!');
// 判断是否之前对该事件进行监听了
const listeners = this.listeners[type];
if (!listeners) throw new Error(`没有对象监听 ${type} 事件!`);
if (!event.target) event.target = this;
listeners.forEach(l => {
l(event);
// 如果通过 once 监听,执行一次后取消
if (l._once) this.off(type, l);
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 测试
function handleMessage(event) { console.log(`message received: ${ event.message }`); }

function handleMessage2(event) { console.log(`message2 received: ${ event.message }`); }

const target = new EventTarget();

target.on('message', handleMessage);
target.on('message', handleMessage2);
target.trigger({ type: 'message', message: 'hello custom event' }); // 打印 message,message2

target.off('message', handleMessage);
target.trigger({ type: 'message', message: 'off the event' }); // 只打印 message2

target.once('words', handleMessage);
target.trigger({ type: 'words', message: 'hello2 once event' }); // 打印 words
target.trigger({ type: 'words', message: 'hello2 once event' }); // 报错:没有对象监听 words 事件!
本文结束感谢您的阅读

本文标题:事件机制

文章作者:陈宇(cosyer)

发布时间:2019年11月24日 - 22:11

最后更新:2019年11月25日 - 23:11

原始链接:http://mydearest.cn/2019/%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85%E6%A8%A1%E5%BC%8F.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!