做爲一名軟件開發人員,瞭解經常使用的設計模式應該算是咱們必備的技能之一了。若是你在編程中能夠駕輕就熟的使用這些,那你的代碼確定是知足了健壯性,可讀性,易維護的範疇以內的。本章咱們一塊兒來了解下前端開發中經常使用的設計模式發佈 訂閱。前端
說道發佈訂閱者模式,那不得不提的就是觀察者模式,讓咱們先來對比下他們基礎特性(摘自維基百科):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