初探Vue原理之view-model的資料動態雙向繫結
阿新 • • 發佈:2019-01-04
Vue應用的是mvvm框架,view和model分離,然後通過vm雙向資料繫結,`
<!-- 模板 -->
<div id="app">
{{msg}}
</div>
<!-模型->
// 原生物件即資料
var data = {
msg: 'hello!'
}
// 建立一個 ViewModel 例項
var vm = new Vue({
// 選擇目標元素
el: '#app',
// 提供初始資料
data: data
})
然而一個動態資料的繫結,是怎麼實現的呢,首先Vue利用es5的defineProperty方法裡的get,set方法,進行資料的設定和獲取。
Object.defineProperty(Vue.prototype, '$data', {
get () {
return this._data
},
set (newData) {
if (newData !== this._data) {
this._setData(newData)
}
} })
從這段原始碼可以看出設定資料時會呼叫setData方法,而setData的實現如下
Vue.prototype._setData = function (newData) {
newData = newData || {}
var oldData = this._data
this._data = newData
var keys, key, i
// unproxy keys not present in new data
keys = Object.keys(oldData)
i = keys.length
while (i--) {
key = keys[i]
if (!(key in newData)) {
this._unproxy(key)
}
}
// proxy keys not already proxied,
// and trigger change for changed values
keys = Object.keys(newData)
i = keys.length
while (i--) {
key = keys[i]
if (!hasOwn(this, key)) {
// new property
this._proxy(key)
}
}
oldData.__ob__.removeVm(this)
observe(newData, this)
this._digest()
}
這段程式碼的後三行可知首先移除舊的資料,然後呼叫observe(newData, this);
export function observe (value, vm) {
if (!value || typeof value !== 'object') {
return
}
var ob
if (
hasOwn(value, '__ob__') &&
value.__ob__ instanceof Observer
) {
ob = value.__ob__
} else if (
shouldConvert &&
(isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value)
}
if (ob && vm) {
ob.addVm(vm)
}
return ob
}
根據新的資料建立一個新的觀察物件,這裡提一下,vue用的是訂閱模式,首先會把每個資料訂閱一下,當資料變化時,會通知watcher重新計算值
最後一行程式碼this._digest()就是通知更新物件的值,把物件設定成newData,我理解的大概過程是這樣的,大家看到有錯誤理解的歡迎給我指出來。這裡提醒一下之前犯過的錯誤,例如:
<template>
<p>{{user.sex}}</p>
</template>
Data(){
User:{}
}
Ready(){
This.user={name:’smx’,age:12};
This.user.sex=’女’;
}
這將在視圖裡面無法顯示,this.user是通過defineProperty裡set方法設定進去的,所以在後面再設定屬性的時候物件將不能跟蹤到該屬性