做为一名软件开发人员,了解经常使用的设计模式应该算是咱们必备的技能之一了。若是你在编程中能够驾轻就熟的使用这些,那你的代码确定是知足了健壮性,可读性,易维护的范畴以内的。本章咱们一块儿来了解下前端开发中经常使用的设计模式发布 订阅。前端
说道发布订阅者模式,那不得不提的就是观察者模式,让咱们先来对比下他们基础特性(摘自维基百科):vue
从他们对比的特征中不难发现这二者有不少类似点:都是一对多的关系,(一个观察者对象对应多个观察者、一个发布对应多个订阅者。)都能实现数据的绑定。他们本质上的区别是发布订阅会引入Event Channel(订阅器) 来将发布的信息分发到订阅者 (因此发布订阅能够异 步处理订阅的内容)。react
//实现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()
}
})
}
//实现订阅者
复制代码
//实现订阅器
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.订阅发布模式须要维护事件列队,订阅的事件越多,内存消耗越大bash
在vue中数据改变如何通知视图变化的?架构
解析指令 ===> 数据劫持 ===> 触发更新(经过watcher中的set)框架
在vue到双向绑定中订阅器如何分发数据到对应到订阅者?ui
前期也写过总结vue源码的相关文章,那我为什么此时还要再写一篇此类文章?由于随着深刻对vue的使用,渐渐发现掌握vue双向绑定的设计结构是如此重要,vue的此种设计不只能够应用于软件开发中的多种场景,并且是咱们熟练掌握vue这个开发框架的必经之路。this