vue 对于 mvvm 的实现是基于 Object.defineProperty
来实现的,
对于 es6
而言有另外一种类似的监视对象属性变化的 api
, 即使用代理 Proxy
对于这个 api
不熟悉的开发者可以点击这里
利用 porxy
代理对象的 get
, defineProperty
, deleteProperty
方法即可实现,代码简洁明了
const watch = (object, onChange) => {
const handler = {
/*
如果 target[property] 为对象时递归代理,否则返回属性值
@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)
}
},
/*
当对象赋值的时候,触发的代理方法(如果有 set 代理, 则触发 set 代理,否则触发该方法)
@param {object} target
@param {string} property
@param {object} descriptor
*/
defineProperty (target, property, descriptor) {
onChange() // 赋值时触发回调函数
return Reflect.defineProperty(target, property, descriptor)
},
/*
当删除对象属性时触发的代理方法
@param {object} target
@param {string} property
*/
deleteProperty (target, property) {
onChange() // 删除属性时触发回调函数
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'