Vue 高階系列之響應式原理及實現

2021-08-29 18:11:00 字數 3711 閱讀 8704

reactivity表示乙個狀態改變之後,如何動態改變整個系統,在實際專案應用場景中即資料如何動態改變dom。

現在有乙個需求,有a和b兩個變數,要求b一直是a的10倍,怎麼做?

簡單嘗試1:

let a = 3;

let b = a * 10;

console.log(b); // 30

複製**

乍一看好像滿足要求,但此時b的值是固定的,不管怎麼修改a,b並不會跟著一起改變。也就是說b並沒有和a保持資料上的同步。只有在a變化之後重新定義b的值,b才會變化。

a = 4;

console.log(a); // 4

console.log(b); // 30

b = a * 10;

console.log(b); // 40

複製**

簡單嘗試2:

將a和b的關係定義在函式內,那麼在改變a之後執行這個函式,b的值就會改變。偽**如下。

onachanged(() => )

複製**

所以現在的問題就變成了如何實現onachanged函式,當a改變之後自動執行onachanged,請看後續。

結合view層

現在把a、b和view頁面相結合,此時a對應於資料,b對應於頁面。業務場景很簡單,改變資料a之後就改變頁面b。

document

.queryselector('.cell.b')

.textcontent = state.a * 10

複製**

現在建立資料a和頁面b的關係,用函式包裹之後建立以下關係。

onstatechanged(() => )

複製**

再次抽象之後如下所示。

}

onstatechanged(() => )

複製**

view = render(state)是所有的頁面渲染的高階抽象。這裡暫不考慮view = render(state)的實現,因為需要涉及到dom結構及其實現等一系列技術細節。這邊需要的是onstatechanged的實現。

實現方式是通過object.defineproperty中的gettersetter方法。具體使用方法參考如下鏈結。

mdn之object.defineproperty

需要注意的是getset函式是訪問描述符,valuewritable函式是資料描述符。描述符必須是這兩種形式之一,但二者不能共存,不然會出現異常。

例項1:實現convert()函式

要求如下:

示例:

const obj = 

convert(obj)

obj.foo // 輸出 getting key "foo": 123

obj.foo = 234 // 輸出 setting key "foo" to 234

obj.foo // 輸出 getting key "foo": 234

複製**

在了解object.definepropertygettersetter的使用方法之後,通過修改getset函式就可以實現onachangedonstatechanged

實現:

function convert (obj) ": $`)

return internalvalue

},set (newvalue) " to: $`)

internalvalue = newvalue}})

})}複製**

例項2:實現dep

要求如下:

示例:

const dep = new dep()

autorun(() => )

// 註冊訂閱者,輸出 updated

dep.notify()

// 通知改變,輸出 updated

複製**

首先需要定義autorun函式,接收update函式作為引數。因為呼叫autorun時要在dep中註冊訂閱者,同時呼叫dep.notify()時要重新執行update函式,所以dep中必須持有update引用,這裡使用變數activeupdate表示包裹update的函式。

實現**如下。

let activeupdate = null 

function autorun (update)

}複製**

實現**如下。

class dep 

// 訂閱update函式列表

depend ()

} // 所有update函式重新執行

notify ()

}複製**

結合上面兩部分就是完整實現。

例項3:實現響應式系統

要求如下:

示例:

const state = 

observe(state)

autorun(() => )

// 輸出 count is: 0

state.count++

// 輸出 count is: 1

複製**

結合例項1和例項2之後就可以實現上述要求,observe中修改obj屬性的同時分配dep的例項,並在get中註冊訂閱者,在set中通知改變。autorun函式儲存不變。 實現如下:

class dep 

// 訂閱update函式列表

depend ()

} // 所有update函式重新執行

notify ()

}function observe (obj) ,

// setter負責通知改變

set (newval) }})

})return obj

}let activeupdate = null

function autorun (update)

}複製**

結合vue文件裡的流程圖就更加清晰了。

job done!!! 交流

vue響應式布局 Vue 響應式原理

vue2 的資料偵測 在 src observer 目錄裡面,元件例項在初始化時,會呼叫 observe 函式處理 data function initdata vm observe 改寫了所有物件屬性的 getter setter 和陣列原型上的 7 個會改寫陣列方法,從而讓 data 變成可響應...

vue響應式原理

響應式系統是vue框架核心的部分,資料物件僅僅是普通的 js物件。當我們改變資料時,檢視也會被改變,本文就來 一下vue 的響應式原理。vue響應式的核心是使用了es5 新增的api object.defineproperty 因此vue不支援ie8 object.defineproperty的作用...

vue響應式原理

要了解響應式原理首先應該知道什麼是響應式 更改 vue的響應式原理是什麼 vue資料的雙向繫結是通過資料劫持結合發布訂閱模式,偵測到資料變化,然後通過object.defineproperty 物件對每個屬性的getter和setter進行劫持。當讀取 data 中的資料時自動呼叫 get 方法,當...