Vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,今天先講一下数据劫持并實現一個簡單的模型。
Object.defineProperty()
vue是通过Object.defineProperty()裡的getter和 setter 来实现数据劫持的。當我們訪問一個帶有getter的對象属性時,就會觸發getter函數,执行时不传入任何参数,但是会传入 this 对象,该函数的返回值会被用作属性的值。setter同理,不過setter是在修改值時觸發,以及它接受一个参数(也就是被赋予的新值)。
Vue在初始化時會為data內所有属性設定getter與setter,當我們修改值時會觸發setter,把新值傳回去并保存起來,當訪問時則觸發getter取值。
let vm = new Vue({
//把data對象傳入,并為內裡所有屬性設定getter與setter
data:{
name:'peter',
age:'25',
occupation:'web developer'
}
})
實現一個簡單的模型
首先要對參數進行判斷,參數必須要為非空對象,同時要排除數組(typeof array為對象,要用Array.isArray()判斷)
function isObject (obj) {
//如果是object則return true
return typeof obj === 'object'
&& !Array.isArray(obj)
&& obj !== null
&& obj !== undefined
}
function convert (obj) {
//對象判斷
if (!isObject(obj)) {
return
}
//遍歷所有屬性鍵
Object.keys(obj).forEach(key => {
//保存值
let Value = obj[key]
Object.defineProperty(obj, key, {
get () {
console.log(`getting key "${key}": ${Value}`)
return Value
},
set (newValue) {
console.log(`setting key "${key}" to: ${newValue}`)
//重寫值
Value = newValue
}
})
})
}
測試
把對象放進去測試
當修改與取值時都會觸發我們定義好的getter和 setter,我們已經對obj內所有屬性进行劫持监听,只要再将一些更新的方法放在setter就可以實現data更新view了。