Vue的響應(yīng)式原理是基于發(fā)布訂閱模式實現(xiàn)的。所以先來了解一下發(fā)布訂閱模式【Publish-Subscribe Pattern】
了解前端常見的兩種設(shè)計模式
發(fā)布-訂閱模式 Publish-Subscribe Pattern
由發(fā)布者Publisher
、訂閱者列表Subscriber
、消息隊列/調(diào)度中心Event Channel
組成的形式。發(fā)布者Publisher
和訂閱者Subscriber
之間是互不相識,不直接通信交流的,而是通過消息隊列進(jìn)行。
可以理解為:某博主(發(fā)布者)發(fā)布了一個短視頻在短視頻平臺(消息隊列)上,每天上班搬磚的打工人(訂閱者)趁著吃飯的時間,刷刷短視頻,發(fā)現(xiàn)該博主的視頻非常優(yōu)秀有內(nèi)容,于是在該短視頻平臺上訂閱關(guān)注了該視頻博主。然后該博主只要更新了視頻,你就能接收到通知。
特點
- 松解耦:發(fā)布者訂閱者通過中介進(jìn)行通信,互不知曉對方存在。降低了組件間的耦合度,使得更容易理解維護(hù)和擴展。
- 擴展性:由于解耦性,可以更容易擴展。新增發(fā)布者或訂閱者不影響現(xiàn)有組件。
- 靈活性:允許任何數(shù)量的發(fā)布者訂閱者存在,支持多對多通信。刪除、修改、新增不影響系統(tǒng)運行。
- 異步通信:支持異步通信,能更高效處理消息,提高響應(yīng)性。
舉例子
class eventChannel {
constructor() {
this.msgMap = {}
}
publish(name, param) {
const msg = this.msgMap[name]
if (msg) {
msg.subscribeList.forEach(subscribe => {
subscribe.callback(param)
})
}
}
subscribe(name, callback) {
const msg = this.msgMap[name]
if (msg) {
msg.subscribe.push({callback})
} else {
this.msgMap[name] = {
name,
subscribeList: [{callback}]
}
}
}
}
觀察者模式 Observer Pattern
面試有時候會被問到觀察者模式和發(fā)布-訂閱模式之間有什么不同。簡單的說:觀察者(Observer)直接訂閱(Subscribe)主題(Subject),而當(dāng)主題被激活的時候,會觸發(fā)(Fire Event)觀察者里的事件,沒有中介代替?zhèn)鬟f消息。
觀察者模式定義了對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知,并自動更新。觀察者模式屬于行為型模式,行為型模式關(guān)注的是對象之間的通訊,觀察者模式就是觀察者和被觀察者之間的通訊。
特點
- 松耦合:實現(xiàn)了主題和觀察者之間的松耦合。
- 一對多關(guān)系:一個主題可以有多個觀察者。
- 可擴展性:可以隨時添加新的觀察者,或刪除現(xiàn)有觀察者。
- 實時性:主題發(fā)生變化時,觀察者能立刻收到通知。
舉例子
let observerIds = 0
// 被觀察者
class Subject {
constructor() {
this.observeres = []
}
addObservere(observer) {
this.observeres.push(observer)
}
removeObservere(obs) {
this.observeres = this.observeres.filter(observer => observer !== obs )
}
notify(data) {
this.observeres.forEach(observer => observer(data))
}
}
// 觀察者
class Observer {
constructor() {
this.id = observerIds++
}
update(ob) {
// ...
}
}
Vue2 數(shù)據(jù)響應(yīng)式原理
Vue2的數(shù)據(jù)對象是通過Object.defineProperty
進(jìn)行數(shù)據(jù)劫持, 將其對象屬性轉(zhuǎn)化為響應(yīng)式屬性。同時,為每個屬性創(chuàng)建一個Dep
對象,收集當(dāng)前屬性的依賴關(guān)系。這里的Dep
就相當(dāng)于上文發(fā)布訂閱模式中講到的調(diào)度中心。
當(dāng)讀取數(shù)據(jù)時會觸發(fā)getter,修改數(shù)據(jù)時會觸發(fā)setter。Watcher對象作用是建立依賴關(guān)系,檢測數(shù)據(jù)變化,并在數(shù)據(jù)變化時執(zhí)行相應(yīng)的更新操作。Watcher機制是基于異步更新的,這樣能避免頻繁更新,提高性能和優(yōu)化用戶體驗。
Vue3 數(shù)據(jù)響應(yīng)式原理
Vue3 是基于proxy的Observer,通過Proxy
攔截對象屬性變化,通過Reflect
對原對象屬性進(jìn)行操作。
Proxy
:在目標(biāo)對象之前假設(shè)一層攔截,可以對外界的訪問進(jìn)行改寫??梢酝ㄟ^其get捕獲器
攔截讀取對象屬性,通過set捕獲器
攔截對象屬性賦值。
Reflect
:提供了一組和Objct類似的方法,用于操作對象。Vue3中主要配合Proxy進(jìn)行操作,以獲取/設(shè)置代理對象屬性值。
Vue3使用Proxy
替代Obejct.defineProperty
,解決了以下問題:
- 優(yōu)化數(shù)組監(jiān)聽:
Proxy
可以直接攔截數(shù)組索引設(shè)置和長度變更。 - 嵌套對象處理:Vue2需要遞歸對每個子對象進(jìn)行數(shù)據(jù)攔截,而
Proxy
代理整個對象,無論層級多深都能有效追蹤數(shù)據(jù)變化。 - 全面屬性監(jiān)聽:Vue2只能監(jiān)聽已注冊的屬性,Vue3能對對象屬性的新增刪除修改做全面監(jiān)聽和數(shù)據(jù)變化追蹤。
該文章在 2024/4/28 21:13:50 編輯過