vue 對(duì)于 mvvm 的實(shí)現(xiàn)是基于 Object.defineProperty
來(lái)實(shí)現(xiàn)的僧凤,
對(duì)于 es6
而言有另外一種類(lèi)似的監(jiān)視對(duì)象屬性變化的 api
, 即使用代理 Proxy
對(duì)于這個(gè) api
不熟悉的開(kāi)發(fā)者可以點(diǎn)擊這里
利用 porxy
代理對(duì)象的 get
, defineProperty
, deleteProperty
方法即可實(shí)現(xiàn),代碼簡(jiǎn)潔明了
const watch = (object, onChange) => {
const handler = {
/*
如果 target[property] 為對(duì)象時(shí)遞歸代理绘雁,否則返回屬性值
@param {object} target
@param {string} property
@param {object} [receiver]
*/
get (target, property, receiver) {
try {
return new Proxy(target[property], handler)
} catch (err) {
return Reflect.get(target, property, receiver)
}
},
/*
當(dāng)對(duì)象賦值的時(shí)候,觸發(fā)的代理方法(如果有 set 代理展蒂, 則觸發(fā) set 代理钻弄,否則觸發(fā)該方法)
@param {object} target
@param {string} property
@param {object} descriptor
*/
defineProperty (target, property, descriptor) {
onChange() // 賦值時(shí)觸發(fā)回調(diào)函數(shù)
return Reflect.defineProperty(target, property, descriptor)
},
/*
當(dāng)刪除對(duì)象屬性時(shí)觸發(fā)的代理方法
@param {object} target
@param {string} property
*/
deleteProperty (target, property) {
onChange() // 刪除屬性時(shí)觸發(fā)回調(diào)函數(shù)
return Reflect.deleteProperty(target, property)
}
}
return new Proxy(object, handler)
}
// demo
let obj = {
a: 123,
b: {
c: 333
}
}
let i = 0
let watchObj = watch(obj, () => {console.log('Object changed:', ++i)})
watchObj.a = 333
// => 'Object changed: 1'
watchObj.b.c = 444
//=> 'Object changed: 2'