商务网站的功能和建设,创建站点的步骤,lnmp搭建网站,wordpress主题的安装教程目录 前言一、发布订阅模式什么是发布订阅模式#xff1f;应用场景 二、观察者模式1#xff09;什么是观察者模式#xff1f;2#xff09;应用场景3#xff09;vue中的观察者模式观察者#xff08;订阅者#xff09; - Watcher目标者#xff08;发布者#xff09; - D… 目录 前言一、发布订阅模式什么是发布订阅模式应用场景 二、观察者模式1什么是观察者模式2应用场景3vue中的观察者模式观察者订阅者 - Watcher目标者发布者 - Dep没有事件中心 三、发布订阅模式和观察者模式的区别1从组成分析2从关系上分析3从使用角度分析 前言
观察者模式和发布订阅模式作为日常开发中经常使用到的模式我一直不能做到很好的区分。最近在看Vue的源码里面设计到了观察者模式比较感兴趣就去学习了下这里做个总结吧。
一、发布订阅模式
什么是发布订阅模式
基于一个事件中心接收通知的对象是订阅者需要先订阅某个事件触发事件的对象是发布者发布者通过触发事件通知各个订阅者。 举例比如平时订阅的微信公众号这里就涉及到两个角色公众号事件中心和订阅了公众号的用户订阅者。当公众号的作者发布了文章之后订阅公众号的用户就会收到消息这里又涉及到了一个角色公众号的作者发布者. 应用场景
vue中的事件总线就是使用的发布订阅模式它使用 $emit 、$on 进行兄弟组件通信进行参数传递。
手动实现vue中的发布订阅模式
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleVue 中发布订阅模式/title
/head
bodyscript srchttps://cdn.jsdelivr.net/npm/vue/dist/vue.js/scriptscript // Vue 的实例创建事件总线let bus new Vue()// 订阅事件bus.$on(eventName1, val {console.log(eventName1----, val)})bus.$on(eventName2, val {console.log(eventName2----, val)})// 发布事件bus.$emit(eventName1, eventName1)bus.$emit(eventName2, eventName2)}/script
/body
/html打印结果 在上述代码中bus 就是我们创建的 事件总线它是一个 Vue 实例。我们可以在不同的组件中引入这个实例并使用 $on 方法来监听事件使用 $emit 方法来触发事件。通过共享同一个事件总线实例不同组件之间可以通过事件进行通信实现解耦。
需要注意的是使用 事件总线模式 时要确保在适当的时候 销毁 事件总线以避免出现 内存泄漏 的问题。可以在组件的生命周期钩子中销毁事件总线
beforeDestroy() {bus.$off();
}二、观察者模式
1什么是观察者模式
目标者对象 和 观察者对象 有相互依赖的关系观察者对某个对象的状态进行观察如果对象的状态发生改变就会通知所有依赖这个对象的观察者进行更新操作。
观察者模式相比发布订阅模式少了个 事件中心 。
目标者对象【Subject】是被观察的对象它维护一组观察者并提供用于 添加、删除和通知 观察者的方法。观察者对象【Observe】接收 Subject 状态变更通知并处理。目标者对象【Subject】状态变更时通知所有观察者对象【Observe】进行更新操作。
2应用场景
观察者模式在Vue中应用场景数据响应式变化。
在上一篇 Vue源码学习 - 数据响应式原理 文章中已经了解到每个响应式属性都有 一个 dep实例 dep存放了依赖这个属性的 watcherwatcher是观测数据变化的函数如果数据发生变化dep 就会通知所有依赖它的 观察者watcher 去调用更新方法。因此观察者需要被目标对象收集目的是通知依赖它的所有观察者。 为什么watcher中也要存放dep呢原因是因为当前正在执行的 watcher 需要知道此时是哪个 dep 通知了自己。
3vue中的观察者模式
观察者订阅者 - Watcher
update() 当事件发生时具体要做的事情。
目标者发布者 - Dep
subs数组存储所有的观察者。addSub()添加观察者。removeSub()移除观察者。notify()通知观察者 当事件发生后调用所有观察者的update()。
没有事件中心
手动实现观察者模式
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title观察者模式/title
/head
bodyscript// 目标者发布者class Dep {constructor () {// 记录所有的订阅者this.subs []}// 添加订阅者addSub (sub) {if (sub sub.update) {this.subs.push(sub)}}// 发布通知notify () {this.subs.forEach(sub {sub.update()})}}// 观察者订阅者class Watcher {update () {console.log(update)}}//创建实例化对象 测试一下let dep new Dep()let watcher new Watcher()let watcher1 new Watcher()// 添加订阅者dep.addSub(watcher)dep.addSub(watcher1)// 开启通知dep.notify()// 执行结果 update ---/script
/body
/html
打印结果触发两次更新通知。 三、发布订阅模式和观察者模式的区别
1从组成分析
观察者模式里只有两个角色观察者 和 目标者也可以叫被观察者。其中 被观察者 是重点。发布订阅模式里不仅仅只有 发布者 和 订阅者还有一个 事件中心。其中 事件中心 是重点。
观察者模式发布订阅模式2个角色3个角色重点是 被观察者目标者重点是 事件中心
2从关系上分析
观察者和目标者是松耦合的关系发布者和订阅者则完全不存在耦合
3从使用角度分析
观察者模式多用于 单个应用内部 Vue中的数据响应式变化就是观察者模式发布订阅模式更多用于 跨应用的模式比如我们常用的 消息中间件
可参考 发布订阅模式和观察者模式