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
中的getter
和setter
方法。具體使用方法參考如下鏈結。
mdn之object.defineproperty需要注意的是
get
和set
函式是訪問描述符,value
和writable
函式是資料描述符。描述符必須是這兩種形式之一,但二者不能共存,不然會出現異常。
例項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.defineproperty
中getter
和setter
的使用方法之後,通過修改get
和set
函式就可以實現onachanged
和onstatechanged
。
實現:
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 方法,當...