通俗的说,发布订阅模式就是执行一个操作(如点击按钮,执行click事件)调用多个事件。
比如报社和订阅者。报社一更新报纸,订阅者就能接收到快递员传递过来的新报纸。
- 一、jquery
jquery.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="submit">submit</button>
<script src="dist/jquery.min.js"></script>
<script>
// jQuery中的发布订阅思想 $.fire(),$.add(),$.remove()
let f1 = function () {
console.log("1")
}
let f2 = function () {
console.log("2")
}
let f3 = function () {
console.log("3")
}
// 1.非发布订阅的执行方法
/*
$('.submit').click(function () {
f1();
f2();
f3();
})
*/
// 2. 发布订阅的执行方法
// (1).创建一个事件池$.Callbacks()
let $pond1 = $.Callbacks();
$('.submit').click(function () {
$pond1.fire(100,200);
});
let f4 = function (a,b) {
console.log("4:",a+b)
};
// (2).需要做的事情添加到事件池中
// 添加删除方法:$pond.add(fun) / $pond.remove(fun)
$pond1.add(f1);
$pond1.add(f2);
$pond1.add(f3);
$pond1.add(f4);
// 移除方法
$pond1.remove(f1)
</script>
</body>
</html>
- 二、JavaScript
1.封装方法subscribe.js
let _subscribe = (function() {
// Sub:发布订阅类
class Sub{
constructor(){
// 创建一个事件池,用来存储后期需要执行的方法
this.$pond = [];
}
// 向事件池中添加方法(重复处理)
add(func){
let flag = this.$pond.some(item=>{
return item === func
});
!flag? this.$pond.push(func) :null;
}
// 从事件池中移除方法
remove(func){
let $pond = this.$pond;
for (let i=0;i<$pond.length;i++){
let item = $pond[i];
if(item === func){
// $pond.splice(i,1);移除,不能改变顺序splice,不能这样写,这样会
// 导致数组塌陷问题,我们移除不能真移除,只能把当前赋值为null
$pond[i] = null; // 1.设置为空,不改变索引
break;
}
}
}
//通知事件池中的方法,按照顺序依次执行
fire(...args){
let $pond = this.$pond;
for (let i=0;i<$pond.length;i++){
let item = $pond[i];
if(typeof item !== 'function'){
// 删除
// 2.此时再删除
$pond.splice(i,1);// 删除后,索引需要变小
i--;
continue;
}
item.call(this,...args);
}
}
}
// 暴露给外面用
return function subscribe() {
return new Sub();
}
})();
// let s1 = new Sub();
// 调用
// let s1 = _subscribe();
2.引用index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="submit">submit</button>
<script src="subscribe.js"></script>
<script>
let pond = _subscribe();
document.querySelector('.submit').onclick=function (ev) {
pond.fire(ev);
};
let f1 = function () {
console.log("1")
};
let f2 = function () {
console.log("2");
pond.remove(f1);// 这样会导致数组塌陷问题,结果:124;234;234 。.
// 移除数组的某一项,索引向前移动,但是我们还在按照之前的顺序执行
};
let f3 = function () {
console.log("3")
};
pond.add(f1);
pond.add(f1); // 自己的方法有去重
pond.add(f2);
pond.add(f3);
let f4 = function (ev) {
console.log("4",ev)
};
pond.add(f4);
// 移除
// pond.remove(f2);
</script>
</body>
</html>
打印如图