发布订阅模式:订阅者,发布者,信号中心

我们假定,存在一个“信号中心”,某个任务执行完成,就向信号中心"发布"(publish)一个信号,其它任务可以向信号中心“订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe
pattern)
家长向学生所在的班级订阅了获取学生考试成绩的事件,当老师公布学生的成绩后,就会自动通知学生的家长。

在整个案例中,学生所在的班级为信号中心,老师为发布者,家长为订阅者

Vue 的自定义事件就是基于发布订阅模式来实现的。

下面通过Vue中兄弟组件通信过程,来理解发布订阅模式
// eventBus.js // 事件中心 let eventHub=new Vue() //ComponentA.vue
addTodo:function(){    //发布消息(事件)  
 eventHub.$emit('add-todo',{text:this.newTodoText})    this.newTodoText='' }
//ComponentB.vue //订阅者 created:function(){    //订阅消息(事件)  
 eventHub.$on('add-todo',this.addTodo) }
通过以上代码,我们可以理解发布订阅模式中的核心概念。

下面我们模拟Vue中的自定义事件的实现

下面我们先来做一个基本的分析:

先来看如下代码:
<!DOCTYPE html> <html lang="en">  <head>    <meta charset="UTF-8" />    <meta
name="viewport" content="width=device-width, initial-scale=1.0" />  
 <title>Vue 自定义事件</title>  </head>  <body>    <script
src="./js/vue.js"></script>    <script>      //Vue自定义事件      let vm = new
Vue();      //注册事件(订阅消息)      vm.$on("dataChange", () => {      
 console.log("dataChange");     });      vm.$on("dataChange", () => {      
 console.log("dataChange");     });      //触发事件(发布消息)    
 vm.$emit("dataChange");    </script>  </body> </html>
通过上面的代码,我们可以看到$on实现事件的注册,而且可以注册多个事件,那么我们可以推测在其内部有一个对象来存储注册的事件,对象的格式为:
{'click':[fn1,fn2],'change':[fn]}
以上格式说明了,我们注册了两个事件,分别为click与change.

下面我们根据以上的分析过程,来模拟实现自定义事件。
<!DOCTYPE html> <html lang="en">  <head>    <meta charset="UTF-8" />    <meta
name="viewport" content="width=device-width, initial-scale=1.0" />  
 <title>发布订阅模式</title>  </head>  <body>    <script>      class EventEmitter {  
     constructor() {          // {'click':[fn1,fn2],'change':[fn]}          //
存储事件与处理函数的对应关系          this.subs = {};       }        //注册事件      
 //第一个参数为事件名称        // 第二个参数为处理函数        // 将对应的处理函数添加到subs对象中      
 $on(eventType, fn) {        
 //判断对应的eventType是否有相应的处理函数,如果有,直接添加到数组中,如果没有返回一个空数组。          if
(!this.subs[eventType]) {            this.subs[eventType] = [];         }      
   this.subs[eventType].push(fn);       }        //触发事件        $emit(eventType)
{          if (this.subs[eventType]) {          
 this.subs[eventType].forEach((handler) => {              handler();          
});         }       }     }      //测试代码      let em = new EventEmitter();    
 em.$on("click", () => {        console.log("click1");     });    
 em.$on("click", () => {        console.log("click2");     });    
 em.$emit("click");    </script>  </body> </html> ​

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信