简单总结了订阅发布模式的几个步骤:
1、声明一个数组用于缓存订阅用户
let list = []
2、实现订阅功能,参数key用于区分订阅事件,参数fn为回调函数
const listen = function(key,fn){
if(!key || !fn) return;
const item = {
key,
fn
}
list.push(item)
};
3、实现发布功能,通过发布指定的key值,在缓存列表中找到相同key值的订阅用户,将订阅用户的回调函数指向发布者,实现参数传递
const trigger = function(){
const [key,...other] = arguments;
const fns = list.filter( item => item.key === key);
if( fns.length === 0 ) return;
for( let { fn } of fns){
fn.call(this,...other)
}
};
4、移除订阅,通过指定key值跟fn值删除缓存列表的订阅用户,如果没有fn,将删除指定key值的所有订阅用户
const remove = function(key,fn=null){
if(!key) return;//没传key值直接返回
for(let i = list.length - 1;i >= 0; i--){
if(!fn){//没传fn,删除指定key的所有订阅用户
if(key == list[i].key){
list.splice(i,1)
}
}else{//传fn,删除指定key&fn的订阅用户
if(key == list[i].key && fn == list[i].fn){
list.splice(i,1)
}
}
}
}
实现订阅发布的基本功能已经完成,简单封装下如下:
var Event = (function(){
let list = [],
listen,
trigger,
remove;
//订阅
listen = function(key,fn){
if(!key || !fn) return;
const item = {
key,
fn
}
list.push(item)
};
//发布
trigger = function(){
const [key,...other] = arguments;
const fns = list.filter( item => item.key === key);
if( fns.length === 0 ) return;
for( let { fn } of fns){
fn.call(this,...other)
}
};
//移除订阅
remove = function(key,fn=null){
if(!key) return;//没传key值直接返回
for(let i = list.length - 1;i >= 0; i--){
if(!fn){//没传fn,删除指定key的所有订阅用户
if(key == list[i].key){
list.splice(i,1)
}
}else{//传fn,删除指定key&fn的订阅用户
if(key == list[i].key && fn == list[i].fn){
list.splice(i,1)
}
}
}
}
return {
listen,
trigger,
remove
}
})()
基本用法,简单实例如下:
<!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>
</head>
<script src="./pubsub.js"></script>
<body>
</body>
<script>
let fn = function(color){
console.log('k1颜色是'+color)
}
let fn2 = function(color){
console.log('k1-1颜色也是'+color)
}
let fn3 = function(color){
console.log('k2颜色是'+color)
}
Event.listen('k1',fn)
Event.listen('k1',fn2)
Event.listen('k2',fn3)
Event.trigger('k1','红色')
Event.trigger('k2','黑色')
Event.remove('k1',fn2)
console.log('-------移除(k1,fn2)-------')
Event.trigger('k1','紫色')
Event.trigger('k2','蓝色')
</script>
</html>
输出结果如下:
//k1颜色是红色
//k1-1颜色也是红色
//k2颜色是黑色
//-------移除(k1,fn2)-------
//k1颜色是紫色
//k2颜色是蓝色