在 VUE
中關於如何實如今網上能夠搜出很多,在看了部分源碼後,梳理一下內容。vue
首先,咱們須要瞭解一下 js
中的一個 API
:
Object.defineProperty(obj, prop, descriptor)git
通常狀況下咱們爲一個對象添加一個屬性通常都會這麼寫github
let object = {} object.test = 'test'
Object.defineProperty
也能作到一樣的效果數組
let object = {}, test = 'test' Object.defineProperty(object, 'test', { configurable: true, // 描述該屬性的描述符可否被改變,默認值爲 false enumerable: true, // 可否被遍歷,好比 for in,默認值爲 false get: function(){ // 取值的時候調用,object.test,默認值爲 false console.log('enter get') return test }, set: function(newValue){ // 設置值的時候使用 console.log('enter set') test = newValue } })
這樣寫雖然代碼量多了很多,可是卻擁有了控制屬性取值和設置值的權利,讓咱們來測試一下。函數
object.test // enter get // test object.test = 'test2' // enter set // test2
接着咱們把 defindProperty
這個函數封裝同時改造一下,方便咱們調用測試
let callback = { target: null } let defineReactive = function(object, key, value){ let array = [] Object.defineProperty(object, key, { configurable: true, enumerable: true, get: function(){ if(callback.target){ array.push(callback.target) } return value }, set: function(newValue){ if(newValue != value){ array.forEach((fun)=>fun(newValue, value)) } value = newValue } }) }
能夠從代碼中看出來,我在函數內部聲明瞭一個數組用於存放 callback
中的 target
,當對 object
進行 get
操做(取值操做)的時候,就會往 array
中存放函數,進行 set
操做(設置值)的時候執行 array
中的函數。看看效果如何優化
let object = {} defineReactive(object, 'test', 'test') callback.target = function(newValue, oldValue){ console.log('我被添加進去了,新的值是:' + newValue) } object.test // test callback.target = null object.test = 'test2' // 我被添加進去了,新的值是:test2 callback.target = function(newValue, oldValue){ console.log('添加第二個函數,新的值是:' + newValue) } object.test // test callback.target = null object.test = 'test3' // 我被添加進去了,新的值是:test3 // 添加第二個函數,新的值是:test3
這樣咱們就達成了在 object.test
的值發生改變時,運行一個函數隊列(雖然這個隊列挺簡陋的)的目的。code
換個說法,當咱們取值的時候,函數自動幫咱們添加了針對當前值的依賴,當這個值發生變化的時候,處理了這些依賴,好比說 DOM
節點的變化。對象
這個也是 VUE
中實現 MVVM
的最核心的代碼,固然在 VUE
中,這個依賴收集的過程遠比如今的代碼要複雜,這裏僅僅實現了依賴的收集和觸發,對於依賴的管理這裏的代碼還作不到。
只是簡單的瞭解一下 VUE
中依賴收集的過程,關於如何去完美的收集依賴,還須要瞭解幾個感念,以後再說。blog