Vue 2 中的对象代理
什么是对象代理
const vm = new Vue({
data() {
return {
a: {
b: 'bbb'
}
}
}
})
console.log(vm.a)
上述代码中 vm.a 正确输出了 {b: 'bbb'},即 vm 代理了 vm.data()。
这里的代理只是浅代理,并没有递归代理。
实现原理
ES5 Object.defineProperty
function Vue(options) {
const data = options.data(), // options 对象中的 data 函数的返回值
vm = this // 保存 this,构造函数默认返回 this 对象
for (let property in data) { // 遍历 data 属性
;(function (property) { // 包裹一个立即执行函数,为了使每次遍历都有不同的 property 值,否则 property 值只能获取最后一个
Object.defineProperty(vm, property, { // 把每个 property 属性绑定到 vm 对象上,这样,每次使用 vm.a,就会被下面的 get 方法劫持
set(value) {
data[property] = value // 劫持 vm.a = 'aaa',在设置值的同时把 data.a = 'aaa' 也设置上了
},
get() {
return data[property] // 劫持 vm.a,在获取 vm.a 的时候,返回的时 data.a 的值
}
})
})(property)
}
}
ES6 Proxy
function Vue(options) {
const data = options.data()
return new Proxy(data, { // 代理 data 对象,进行数据劫持处理之后,把代理对象 return 即可,vm 实例即代理对象,vm.a 即 proxy.a 即 data.a
set(target, property, value) {
target[property] = value
return true
},
get(target, property) {
return target[property]
}
})
}