subscribe.js 文件
let _subscribe = (function () {
//=> Sub 发布订阅类
class Sub {
constructor() {
//=>创建一个事件池,用来存储后期需要执行的方法
this.$pond = [];
}
//=>向事件池追加方法;
add(func) {
//=>如果传递进来的不是方法,我们不做任何处理
if (typeof func !== 'function') return;
//=>把传递进来的方法,存储到事件池中
//=> 判断事件池中是否有该方法
let flag = this.$pond.some(item => item === func);
!flag ? this.$pond.push(func) : null;
}
//=> 从事件池中移除方法
remove(func) {
if (typeof func !== 'function') return;
let $pond = this.$pond
for(let i = 0; i < $pond.length; i++){
let item = $pond[i];
if(item === func){
//移除(顺序不变的情况下基本上只能用splice)但是不能这样写,这会导致数组坍塌问题,我们移除不能真移除,只能把当前项赋值为null
// $pond.splice(i,1);
$pond[i] = null;
break;
}
}
//=>通知事件池中的方法,按照顺序依次执行
fire(...args) {
let $pond = this.$pond;
for (let i = 0; i < $pond.length; i++) {
let item = $pond[i];
if(typeof item !== 'function'){
//此时在删除
$pond.splice(i,1);
i--;
continue;
}
item.call(this, ...args);
}
}
}
//暴露给外面使用
return function subscribe() {
return new Sub();
}
})();
如何使用:
<body>
<button class="submit">点击</button>
<script src="subscribe.js"></script>
<script>
let $pond = _subscribe();
document.querySelector('.submit').onclick = function (ev) {
$pond.fire([1, 2, 3]);
}
let fn1 = function () {
console.log(1)
}
let fn2 = function () {
console.log(2)
$pond.remove(fn1)
}
let fn3 = function () {
console.log(3)
}
let fn4 = function (ev) {
console.log(4,ev)
}
$pond.add(fn1)
$pond.add(fn2)
$pond.add(fn3)
$pond.add(fn4)
</script>
</body>
点击两次后的效果: