vue響應式原理

2021-09-24 20:57:40 字數 4278 閱讀 1273

響應式系統是vue框架核心的部分,資料物件僅僅是普通的 js物件。當我們改變資料時,檢視也會被改變,本文就來**一下vue 的響應式原理。

vue響應式的核心是使用了es5 新增的api object.defineproperty(因此vue不支援ie8) 。object.defineproperty的作用就是直接在乙個物件上定義乙個新屬性,或者修改乙個已經存在的屬性, 它允許我們為物件的實行設定get和set方法,在物件取值和賦值會呼叫這兩個方法,所以我們可以在賦值和取值時劫持這兩個方法,觸發更新試檢視的操作。

const obj = 

let val = '劫持'

object.defineproperty(obj, 'attr', ,

set(newval)

})console.log(obj.attr)

obj.attr = '賦值'

console.log(obj.attr)

vue的依賴收集使用了發布訂閱模式。

class dep 

// 增加訂閱者

addsub(sub)

// 通知訂閱者

notify() )

}}const dep = new dep()

const sub_fn1 =

}const sub_fn2 =

}dep.addsub(sub_fn1)

dep.addsub(sub_fn2)

dep.notify()

vue在初始化時會條用一系列方法,其中initstate對資料data進行了初始化

export function initstate (vm: component)  else , true /* asrootdata */)

} if (opts.computed) initcomputed(vm, opts.computed)

if (opts.watch && opts.watch !== nativewatch)

}

這段**對props methods data進行了初始化,我們選擇initdata作為切入點來**vue的響應式系統。

function initdata (vm: component) 

if (!isplainobject(data))

process.env.node_env !== 'production' && warn(

'data functions should return an object:\n' +

'',vm

)} const keys = object.keys(data)

const props = vm.$options.props

const methods = vm.$options.methods

let i = keys.length

while (i--) " has already been defined as a data property.`,vm)

}}

if (props && hasown(props, key)) " is already declared as a prop. ` +

`use prop default value instead.`,vm)

} else if (!isreserved(key))

} observe(data, true /* asrootdata */)

}

這段**獲取了data,先判斷了data的型別是不是純物件,然後判斷了data的屬性與props和methods是否衝突,接著在vue 例項物件上新增了訪問資料**物件_data的同名屬性,最後呼叫了observe 函式開啟了資料響應式系統。

因為observe**相對比較複雜,有很多邊界條件的判斷,如避免收集重複的依賴,如何深度觀測,如何處理陣列與物件等,為了簡化理解,我們只關注最核心的邏輯。

export function observe (value: any, asrootdata: ?boolean): observer | void 

let ob: observer | void

if (hasown(value, '__ob__') && value.__ob__ instanceof observer) else if (

shouldobserve &&

!isserverrendering() &&

(array.isarray(value) || isplainobject(value)) &&

object.i***tensible(value) &&

!value._isvue

) if (asrootdata && ob)

return ob

}

這段**是observe的全部內容,observe對data進行了乙個判斷, 如果不是物件或者不是vnode的例項,不進行監測。然後判斷data是否有__ob__ 屬性,如果有直接賦值,避免重複監測,因為物件被監測後會新增__ob__ 屬性。 緊接著又有一些是否可以監測的條件判斷,當滿足時,就會建立乙個observer 例項。

export class observer  else 

this.observearray(value)

} else

} walk (obj: object)

} observearray (items: array)

}}

上面是observer類。this.value = value 是例項化物件時傳進來資料的引用,可以看到def(value, 『ob』, this)這句**為監測物件新增了__ob__屬性,然後判斷時純物件還是陣列,分別走不同的監測邏輯。因為物件相對簡單,我們選擇物件理一下邏輯。當資料是純物件時,會呼叫walk函式,遍歷data所有可列舉的屬性,然後迴圈將這些屬性作為引數呼叫definereactive 函式。

export function definereactive (

obj: object,

key: string,

val: any,

customsetter?: ?function,

shallow?: boolean

) // cater for pre-defined getter/setters

const getter = property && property.get

const setter = property && property.set

if ((!getter || setter) && arguments.length === 2)

let childob = !shallow && observe(val)

object.defineproperty(obj, key, }}

return value

},set: function reactivesetter (newval)

/* eslint-enable no-self-compare */

if (process.env.node_env !== 'production' && customsetter)

// #7981: for accessor properties without setter

if (getter && !setter) return

if (setter) else

childob = !shallow && observe(newval)

dep.notify()}})

}

這段**相對比較複雜,有許多邊界條件的判斷,我們不必關心實現實踐的細節,只關注object.defineproperty即可。definereactive 的核心是將資料物件的屬性用object.defineproperty進行資料劫持 const dep = new dep()定義了依賴收集器。object.defineproperty定義了get和set方法,當執行賦值時,會呼叫get函式執行dep.depend()進行依賴收集,當值改變時呼叫set觸發dep.notify(),進行檢視更新。

vue響應式系統的核心原理是資料劫持結合發布訂閱模式,在vue初始化過程中,vue會對templae編譯生成指令物件與訂閱者關聯,通過object.defineproperty為資料物件新增getter和setter,並執行gettter,新增訂閱者。當資料改變時,觸發setter,訂閱者執行指令更新,指令是對原生dom物件的封裝,從而導致檢視的更新。

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

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

vue響應式原理

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

Vue響應式原理

不要認為資料發生改變,介面跟著更新,是理所當然的 其實並不是理所當然的,內部其實做了很多封裝 div node modules vue dist vue.js script newvue script body 2.當資料發生改變,vue是如何知道要通知哪些人介面發生更新?發布訂閱者模式 newvu...