发布订阅模式
应用场景:
vue兄弟组件之间数据传递、nodejs事件监听
主要成员:
1. 发布者: 在发布者中调用 hub.notify(),或名为 emit()
2. 订阅者: 在订阅者中调用 hub.addSub(),或名为 on()
3. 事件中心:
- hub.subs数组,用于存储所有订阅者;
- hub.addSub(),用于添加订阅到subs数组,参数为订阅名称、回调函数;
- hub.notify(),用于发布消息通知所有订阅执行更新方法:hub.update()
// vue 兄弟组件之间数据传递伪代码
// 事件中心 eventHub
let eventHub = new Vue()
// 组件A:发布者
addTodo: function (){
eventHub.$emit('add-todo', { text: this.newTodoText })
this.newTodoText = ''
}
// 组件B:订阅者
created: function (){
eventHub.$on('add-todo',(e)=>{ })
}
主要特点:
添加订阅、发布消息都是用的事件中心里面的方法,且数据存储和数据更新都是用的事件中心里面的方法;所以真正的观察者和发布者之间没有耦合。
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>发布订阅模式</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<script>
// 发布订阅模式事件中心类
class PublishSubscribe{
constructor(){
this.subs = {} // Object.create(null)
}
// 订阅
addSub(eventType, handler) {
this.subs[eventType] = this.subs[eventType] || []
this.subs[eventType].push(handler)
}
// 发布
notify(eventType){
if(this.subs[eventType]){
this.subs[eventType].forEach(handler => {
handler()
})
}
}
}
// 发布订阅模式使用示例
// 1、vm 为事件中心实例对象
let vm = new PublishSubscribe()
// 2、订阅消息(在订阅者中调用,例如某个组件1中)
vm.addSub("click",()=>{
console.log("click1")
})
vm.addSub("click",()=>{
console.log("click2")
})
vm.addSub("change",()=>{
console.log("change1")
})
// 3、发布消息(在发布者中调用,例如某个组件2中)
vm.notify("click")
vm.notify("change")
</script>
<body>
</body>
</html>
观察者模式
应用场景
vue 双向绑定实现原理
主要成员
1. 发布者 ,发布者为一个对象
- dep.subs数组,用于存储所有订阅者
- dep.addSub()方法,用于添加订阅到subs数组,参数为观察者实例:watcher
- dep.notify()方法,用于发布消息通知所有订阅者们执行更新方法:update()
2. 订阅者/观察者 ,订阅者为一个对象
- watcher.update()方法,用于更新执行消息发布后的更新;可以将某个callback()传递给update()
let dep = new Dep() // 发布者实例化
let watcher = new Watcher() // 观察者实例化
dep.addSub(watcher) // 添加订阅
dep.notify() // 不发通知
主要特点
添加订阅的时候使用 dep.addSub(watcher)、以及发布订阅的时候使用 dep.notify() 通知所有的 watcher 执行 watcher.update();所以发布者和订阅者之间存在依赖;
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>观察者模式</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<script>
// 1、发布者
class Dep{
constructor(){
this.subs = []
}
addSub (sub){
if(sub && sub.update)
this.subs.push(sub)
}
notify (){
this.subs.forEach(sub => sub.update())
}
}
// 2、订阅者、观察者
class Watcher{
constructor(name){
this.name = name
}
update(){
console.log("update:", this.name)
}
}
// 使用观察者模式
let watcher1 = new Watcher("观察者1")
let watcher2 = new Watcher("观察者2")
let dep = new Dep()
dep.addSub(watcher1)
dep.addSub(watcher2)
dep.notify()
</script>
<body>
</body>
</html>
发布订阅、观察者模式的区别?
发布订阅模式
1. 有事件中心、发布者、订阅者三个成员;(事件中心的作用可以隔离发布者和订阅者,去除他们之间的依赖)
2. 事件中心有三个成员:
- subs => 存储订阅者
- addSub() 方法 => 添加订阅者
- notify() 方法 => 通知订阅者更新的
- update() 方法 => 执行更新回调等功能
3. 发布和订阅者是抽象的,通常是在某个方法里调用 addSub() 和 notify() 。
观察者模式
1. 没有事件中心,只有发布者、订阅者两个成员;
2. 发布者中有三个成员:
- subs => 存储订阅者
- addSub() 方法 => 添加订阅者
- notify() 方法 => 通知订阅者更新的
3. 订阅者中必须有一个成员:
- update() 方法 => 执行更新回调等功能
4. 发布和订阅者是一个对象。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。