響應式系統是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...