Vue2.X監聽data變化的核心API—Object.defineProperty基本使用:
Object.defineProperty實現響應式
1.監聽對象(簡單對象)
上面通過監聽get,set方法了解到data變化,進而可以達到響應式。
2.復雜對象(深度監聽),深度監聽
觸發更新視圖
// 觸發更新視圖 function updateView() { console.log('視圖更新') }
在上面例子data加:
// 准備數據 const data = { name: '佩奇', age: 20, info: { address: '寧波' // 需要深度監聽 }, }
// 重新定義屬性,監聽起來 function defineReactive(target, key, value) { // 核心 API Object.defineProperty(target, key, { get() { return value }, set(newValue) { if (newValue !== value) { // 設置新值 // 注意,value 一直在閉包中,此處設置完之后,再 get 時也是會獲取最新的值 value = newValue // 觸發更新視圖 updateView() } } }) } // 監聽對象屬性 function observer(target) { if (typeof target !== 'object' || target === null) { // 不是對象或數組 return target } // 重新定義各個屬性(for in 也可以遍歷數組) for (let key in target) { defineReactive(target, key, target[key]) } }
// 監聽數據 observer(data)
此時我們在上面例子代碼,沒有監聽到。

此時優化一下,在defineReactive方法里加一層監聽。
// 重新定義屬性,監聽起來 function defineReactive(target, key, value) { // 深度監聽 observer(value) // 核心 API Object.defineProperty(target, key, { get() { return value }, set(newValue) { if (newValue !== value) { // 設置新值 // 注意,value 一直在閉包中,此處設置完之后,再 get 時也是會獲取最新的值 value = newValue // 觸發更新視圖 updateView() } } }) }
可以深度監聽到了。
上面二例子, data.age = {num:21} 可以監聽到 而data.age.num = 22 卻沒有監聽到。
此時優化一下,在defineReactive方法中Object.defineProperty里set方法加 深度監聽 observer(newValue)加一層監聽。
// 重新定義屬性,監聽起來 function defineReactive(target, key, value) { // 深度監聽 observer(value) // 核心 API Object.defineProperty(target, key, { get() { return value }, set(newValue) { if (newValue !== value) { // 深度監聽 observer(newValue) // 設置新值 // 注意,value 一直在閉包中,此處設置完之后,再 get 時也是會獲取最新的值 value = newValue // 觸發更新視圖 updateView() } } }) }
監聽數組:
3.幾個缺點
1.深度監聽,需要遞歸到底,一次性計算量大(通過上面的例子)
2.新增屬性,監聽不到 —— 所以有 Vue.set
3.刪除屬性,監聽不到 —— 所有已 Vue.delete