目录
前言
1、发布-订阅模式
定义
手写发布-订阅模式
2、观察者模式
定义
手写观察者模式
3、二者的根本区别
前言
发布-订阅者模式和观察者模式是两种设计模式,本质相同,但是也有区别,在Vue中有不同的应用场景。二ue响应式数据的基础,有关数据代理与数据劫持的知识点,可以参考这篇文章同学刷抖音的间隙,我学会了Vue数据代理与数据劫持的原理_czjl6886的博客-CSDN博客
1、发布-订阅模式
定义
存在一个“信号中心”,某个任务完成,就向信号中心,发布(publish)一个信号,其他任务向信息中心订阅(subscribe)这个信号,从而知道自己什么时候可以开始执行,即:发布-订阅模式。
手写发布-订阅模式
伪代码中:emit触发事件,发布数据,on订阅这个事件,接收该数据 ,即:on-订阅, off取消订阅, emit发布
<script>
class EventEmitter{
constructor(){
// 初始化为一个空的新对象
// 在vm上创建一个_events对象,用来存放事件
this._events=Object.create(null)
}
// 监听事件,获得emit触发事件后提供的数据
on(event,fn){
// 如果是数组,则循环监听数组事件
if(Array.isArray(event)){
event.forEach(item => {
this.on(item,fn)
})
}else{
(this._events[event] || (this._events[event]=[])).push(fn)
}
}
// 关闭事件绑定
off(event,fn){
// 如果参数为空,则关闭所有的事件绑定
if(!arguments.length){
// 重新设置为一个空对象
this._events = Object.create(null)
return
}
// 如果传进来的事件没有emit,则返回;emit用于触发事件
if(!this._events[event]) return
// 如果没有传入回调函数,则默认移除该事件绑定的所有回调函数,
// 否则移除与fn相同的回调
if(!fn){
this._events[event] = []
return
}else{
// this._events[event]是引用数据类型,与cbs指向同一个数据
const cbs = this._events[event]
let i = this._events[event].length
while(i--){
if(cbs[i] === fn || cbs[i].fn === fn){
cbs.splice(i,1)
continue
}
}
}
}
// 只触发一次自定义事件
once(event,fn){
const on=()=>{
// 在第一次执行的时候将该事件销毁
this.off(event,on)
fn.apply(this,arguments)
}
on.fn = fn
this.on(event,on)
}
// 触发事件,提供数据
emit(event,...args){
const cbs=this._events[event]
if(cbs){
cbs.forEach(fn => {
fn.apply(this,args)
})
}
}
}
const initEvent = new EventEmitter()
function fnTest(value){
console.log("This is a event" + value)
}
// 绑定单击事件click与回调函数fnTest
initEvent.on("click",fnTest)
initEvent.once("click",fnTest)
initEvent.emit("click","这个参数指的是emit触发的事件要传递的数据")
// 关闭事件绑定
initEvent.off("click")
</script>
2、观察者模式
定义
当事件发生时,观察者(订阅者,watcher)执行update()方法,完成相应的操作;被观察的目标(发布者,Dep)使用数组subs来存储所有的观察者,也可以使用addSub()添加新的观察者,当有事件发生时,调用所有观察者的update()方法。
手写观察者模式
<script>
// 被观察的目标,即发布者:Dep
class Dep{
constructor(){
// 记录所有的观察者,即订阅者
this.subs = []
}
// 添加新的观察者
addSub(sub){
// 该订阅者存在且有update方法,就将其添加到subs数组中
if(sub && sub.update){
this.subs.push(sub)
}
}
// 移除观察者
removeSub(sub) {
if (this.subs.length) {
let index = this.indexOf(sub)
if (index > -1) {
this.sub.splice(index, 1)
}
}
}
// 发布更新通知
notify(){
this.subs.forEach(item =>{
item.update()
})
}
}
// 观察者,即订阅者
class Watcher{
update(){
console.log("****更新相关数据****")
}
}
let dep = new Dep
let watcher1 = new Watcher
let watcher2 = new Watcher
// 添加新的观察者
dep.addSub(watcher1)
dep.addSub(watcher2)
dep.removeSub(watcher2)
// 发布
dep.notify()
</script>
3、二者的根本区别
发布-订阅模式:由一个统一调度中心调用,发布者和订阅者之间不需要知道对方的存在;
观察者模式:由具体的目标调度,如,某一个事件被触发时,Dep就会调用数组中保存的和这个事件有关系的观察者的方法,因此,观察者模式中的订阅者与发布者之间存在依赖关系;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)