<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>订阅发布</title>
</head>
<body>
<script>
// 创建一个构造函数
function Public() {
//给实例创建一个handlers属性
this.handlers = {};
}
// 给类的原型绑定对象事件
Public.prototype = {
// 创建constructor属性指向原构造函数
constructor: Public,
// 订阅事件
on(eventType, handler) {
// 首先判断是否存在此私有属性(也就是事件类型),若有,则直接push到原有数组里面,若没有,则定义一个空数组储存函数
if (!this.handlers.hasOwnProperty(eventType)) {
this.handlers[eventType] = [];
}
this.handlers[eventType].push(handler);
// 返回实例,从而可以进行链式写法(以下return this含义相同)
return this;
},
// 触发事件(发布事件)
emit(eventType) {
// 将传递过来的参数从位置1截取到末尾,并返回一个数组。
let handlerArgs = Array.prototype.slice.call(arguments, 1);
//遍历这个私有属性(也就是事件类型)的数组里面存储的函数,并将它们执行。
for (let i = 0; i < this.handlers[eventType].length; i++) {
this.handlers[eventType][i].apply(this, handlerArgs);
}
return this;
},
// 删除订阅事件
off(eventType, handler) {
// 取出当前事件类型
let currentEvent = this.handlers[eventType];
let len = 0;
// 判断事件是否存在
if (currentEvent) {
// 取出存储的函数个数
len = currentEvent.length;
// 避免数组塌陷,从后往前遍历删除
for (let i = len - 1; i >= 0; i--) {
if (currentEvent[i] === handler) {
currentEvent.splice(i, 1);
console.log("删除订阅事件成功!");
}
}
}
return this;
},
};
let Publisher = new Public();
function test1(data) {
console.log('test1' + data);
}
function test2(data) {
console.log('test2' + data);
}
//订阅事件test
Publisher.on("test", test1);
Publisher.on("test", test2);
//触发事件test
Publisher.emit("test", "我是第1次调用的参数").emit("test","我是第2次调用的参数"); //链式调用
Publisher.emit("test", "我是第1次调用的参数"); //直接调用
Publisher.emit("test", "我是第2次调用的参数"); //直接调用
// 删除订阅事件test
Publisher.off("test", test2);
Publisher.emit("test", "已经被删除,test1不会再触发");
// 1我是第1次调用的参数
// 2我是第1次调用的参数
// 1我是第2次调用的参数
// 2我是第2次调用的参数
</script>
</body>
</html>
网友评论