詳解Vue響應式原理

2021-10-07 05:25:45 字數 3590 閱讀 9304

什麼是響應式

我們先來看個例子:

total:¥}

taxes: ¥}

改變**

上例中當price 發生變化的時候,vue就知道自己需要做三件事情:

資料發生變化後,會重新對頁面渲染,這就是vue響應式,那麼這一切是怎麼做到的呢?

想完成這個過程,我們需要:

如何偵測資料的變化

方法1. object.defineproperty實現

vue通過設定物件屬性的 setter/getter 方法來監聽資料的變化,通過getter進行依賴收集,而每個setter方法就是乙個觀察者,在資料變更的時候通知訂閱者更新檢視。

function render () 

let data =

}observe(data)

function observe (obj)

object.keys(obj).foreach(key => )

function definereactive (obj, key, value) ,

set: function reactivesetter (newval) }})

}}data.location = //set 模擬檢視渲染

data.name // get 浪裡行舟

上面這段**的主要作用在於:observe這個函式傳入乙個 obj(需要被追蹤變化的物件),通過遍歷所有屬性的方式對該物件的每乙個屬性都通過 definereactive 處理,以此來達到實現偵測物件變化。值得注意的是,observe 會進行遞迴呼叫。那我們如何偵測vue中data 中的資料,其實也很簡單:

class vue 

}

這樣我們只要 new 乙個 vue 物件,就會將 data 中的資料進行追蹤變化。 不過這種方式有幾個注意點需補充說明:無法檢測到物件屬性的新增或刪除(如data.location.a=1)。

這是因為 vue 通過object.defineproperty來將物件的key轉換成getter/setter的形式來追蹤變化,但getter/setter只能追蹤乙個資料是否被修改,無法追蹤新增屬性和刪除屬性。如果是刪除屬性,我們可以用vm.$delete實現,那如果是新增屬性,該怎麼辦呢? 1)可以使用 vue.set(location, a, 1) 方法向巢狀物件新增響應式屬性; 2)也可以給這個物件重新賦值,比如data.location =

object.defineproperty 不能監聽陣列的變化,需要進行陣列方法的重寫,具體**如下:

function render() 

let obj = [1, 2, 3]

let methods = ['pop', 'shift', 'unshift', 'sort', 'reverse', 'splice', 'push']

// 先獲取到原來的原型上的方法

let arrayproto = array.prototype

// 建立乙個自己的原型 並且重寫methods這些方法

let proto = object.create(arrayproto)

methods.foreach(method =>

})function observer(obj)

if (typeof obj == 'object')

}}function definereactive(data, key, value) ,

set(newvalue) }})

}observer(obj)

function $set(data, key, value)

obj.push(123, 55)

console.log(obj) //[1, 2, 3, 123, 55]

方法2. proxy實現

function render() 

let obj = ,

arr: [1, 2, 3]

}let handler =

return reflect.get(target, key)

},set(target, key, value) }​

let proxy = new proxy(obj, handler)

proxy.age.name = '浪裡行舟' // 支援新增屬性

console.log(proxy.age.name) // 模擬檢視的更新 浪裡行舟

proxy.arr[0] = '浪裡行舟' //支援陣列的內容發生變化

console.log(proxy.arr) // 模擬檢視的更新 ['浪裡行舟', 2, 3 ]

proxy.arr.length-- // 無效

訂閱者 dep

class dep 

/* 在subs中新增乙個watcher物件 */

addsub (sub)

/* 通知所有watcher物件更新檢視 */

notify () )}}

以上**主要做兩件事情:

用 addsub 方法可以在目前的 dep 物件中增加乙個 watcher 的訂閱操作;

用 notify 方法通知目前 dep 物件的 subs 中的所有 watcher 物件觸發更新操作。

觀察者 watcher依賴收集的目的是將觀察者 watcher 物件存放到當前閉包中的訂閱者 dep 的 subs 中。.watcher的簡單實現

class watcher 

update()

}

收集依賴

function observe (obj) 

object.keys(obj).foreach(key => )

function definereactive (obj, key, value)

return value

},set: function reactivesetter (newval) }})

}}​class vue

}

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 方法,當...