前言
作为一名软件开发人员,了解常用的设计模式应该算是我们必备的技能之一了。如果你在编程中可以得心应手的使用这些,那你的代码肯定是满足了健壮性,可读性,易维护的范畴之内的。本章我们一起来了解下前端开发中常用的设计模式发布 订阅。
发布订阅者模式是什么
说道发布订阅者模式,那不得不提的就是观察者模式,让我们先来对比下他们基础特性(摘自维基百科):
- 观察者模式:在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。
- 发布订阅者模式:在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。
从他们对比的特征中不难发现这两者有很多相似点:都是一对多的关系,(一个观察者对象对应多个观察者、一个发布对应多个订阅者。)都能实现数据的绑定。他们本质上的区别是发布订阅会引入Event Channel(订阅器) 来将发布的信息分发到订阅者 (所以发布订阅可以异 步处理订阅的内容)。
发布订阅者-vue中的双向绑定
//实现observer数据劫持
export class Observer {
...
//遍历所有属性
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
}
//给属性加上get set
export function defineReactive (
...
) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
...
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
...
dep.notify()
}
})
}
//实现订阅者
- 我们再来看看订阅器中如何实现的,我们订阅器中需要的主要功能收集和发布。 收集observer中劫持到到数据关联对应的数据和订阅者,通知对应的订阅者订阅到数据改变。
//实现订阅器
export default class Dep {
//收集
addSub (sub: Watcher) {
...
}
//
depend () {
if (Dep.target) {
Dep.target.addDep(this)
}
}
//通知
notify () {
...
}
}
*最后我们来了解下订阅者(watcher)接受到订阅器到通知后所做到事情
export default class Watcher {
// ...
/**
* Subscriber interface.
* Will be called when a dependency changes.
*/
// 还记得Dep.notify 调用到update
update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
this.run()
} else {
queueWatcher(this)
}
}
/**
* Scheduler job interface.
* Will be called by the scheduler.
*/
//这个方法并不是实例化Watcher的时候执行的,而是监听的变量变化的时候才执行的
run () {
...
}
}
}
发布订阅的优缺点以及疑问
-
优点:发布者和订阅者是解耦的,符合了软件设计高内聚,低耦合,只要引入订阅发布模式的事件中心,无论在何处都可以发布订阅。同时订阅发布者相互之间不影响。
-
缺点:1.使用不当就会造成数据流混乱,导致代码不好维护。2.订阅发布模式需要维护事件列队,订阅的事件越多,内存消耗越大
-
在vue中数据改变如何通知视图变化的?
解析指令 ===> 数据劫持 ===> 触发更新(通过watcher中的set)
-
在vue到双向绑定中订阅器如何分发数据到对应到订阅者?
总结
前期也写过总结vue源码的相关文章,那我为何此时还要再写一篇此类文章?因为随着深入对vue的使用,渐渐发现掌握vue双向绑定的设计结构是如此重要,vue的此种设计不仅可以应用于软件开发中的多种场景,而且是我们熟练掌握vue这个开发框架的必经之路。