设计模式
设计模式: 一种编程的思想,我们会基于一些代码把思想实现出来,每种设计模式都是解决一类问题,而且问题偏向于"更好的去管理代码"
发布订阅模式
发布订阅设计模式: subscribe & publish 思路一: 全局只有一个自定义池,基于自定义事件的名称来区分要执行的方法 思路二: 基于面向对象管理,每一次new 执行都单独创建一个自定义事件池,实例可以调用: on/off/emit
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
background-color: aqua;
}
</style>
</head>
<body>
<script src="./index.js"></script>
</body>
</html>
const $sub = (function() {
// 自定义事件池
let listeners = {};
// 向事件池i面加入方法
const on = function(name, func) {
let arr = listeners[name];
if(!arr) {
// 事件池中加一个自定义的事件
listeners[name] = [func];
return;
}
// 之前存在这个自定义事件,则方法储存到数组中:去重处理
if(arr.indexOf(func) > -1) return;
arr.push(func);
}
// 从事件池移除方法
const off = function(name, func) {
let arr = listeners[name],
index;
if(!arr) return;
index = arr.indexOf(func);
if(index === -1) return;
// arr.splice(index, 1);//会诞生数组塌陷
arr[index] = null;
}
// 通知事件池中的方法执行
const emit = function(name, ...params) {
let arr = listeners[name];
if(!arr) return;
for(let i = 0; i < arr.length; i++) {
let item = arr[i];
if(typeof item !== "function") {
// 如果当前的不是函数,则把它移除掉
arr.splice(i, 1);
listeners[name] = arr;
i--;
continue;
}
item(...params);
}
}
return {
on,
off,
emit
}
})();
const fn1 = function(x, y) {
console.log('fn1', x + y);
}
$sub.on('@A', fn1);
const fn2 = function fn2(x, y) {
console.log('fn2', x + y);
$sub.off('@A', fn1);
$sub.off('@A', fn2);
}
$sub.on('@A', fn2);
const fn3 = () => console.log("fn3")
$sub.on('@A', fn3);
const fn4 = () => console.log("fn4")
$sub.on('@A', fn4);
const fn5 = () => console.log("fn5")
$sub.on('@A', fn5);
document.body.onclick = function() {
$sub.emit('@A', 10, 20);
}
思路二
class Subscribe {
constructor() {
this.listeners = {}
}
on(name, func) {
let arr = this.listeners[name];
if(!arr) {
// 事件池中加一个自定义的事件
this.listeners[name] = [func];
return;
}
// 之前存在这个自定义事件,则方法储存到数组中:去重处理
if(arr.indexOf(func) > -1) return;
arr.push(func);
}
off(name, func) {
let arr = this.listeners[name],
index;
if(!arr) return;
index = arr.indexOf(func);
if(index === -1) return;
// arr.splice(index, 1);//会诞生数组塌陷
arr[index] = null;
}
emit(name, ...params) {
let arr = this.listeners[name];
if(!arr) return;
for(let i = 0; i < arr.length; i++) {
let item = arr[i];
if(typeof item !== "function") {
// 如果当前的不是函数,则把它移除掉
arr.splice(i, 1);
i--;
continue;
}
item(...params);
}
}
}
const $sub = new Subscribe();
const fn1 = function(x, y) {
console.log('fn1', x + y);
}
$sub.on('@A', fn1);
const fn2 = function fn2(x, y) {
console.log('fn2', x + y);
$sub.off('@A', fn1);
$sub.off('@A', fn2);
}
$sub.on('@A', fn2);
const fn3 = () => console.log("fn3")
$sub.on('@A', fn3);
const fn4 = () => console.log("fn4")
$sub.on('@A', fn4);
const fn5 = () => console.log("fn5")
$sub.on('@A', fn5);
document.body.onclick = function() {
$sub.emit('@A', 10, 20);
}