数据代理
let Proxy = {
name: 'Alice',
age: 18
}
let B = {
gender: 'female'
}
我们可以使用 Object.defineProperty()
方法来给Proxy 对象添加一个gender属性,并为这个属性指定一个getter和setter函数:
Object.defineProperty(Proxy , 'gender', {
get() {
return B.gender // 在getter函数中返回B.gender
},
set(value) {
B.gender = value // 在setter函数中修改B.gender
}
})
Vue中如何使用数据代理
在Vue中,我们通常会创建一个Vue实例,并传入一个选项对象:
let vm = new Vue({
el: '#app',
data: {
name: 'Bob',
age: 20
}
})
在这个选项对象中,有一个data属性,它用来存放我们要渲染到视图上的数据。但是如果我们想要在代码中访问或修改这些数据呢?最直接的方法就是通过vm._data.xxx来实现
但是这样做有点麻烦,因为每次都要多写一个_data。有没有更简单的方法呢?答案就是使用数据代理。
Vue内部会利用 Object.defineProperty()
方法把data对象中所有属性添加到vm上,并为每个添加到vm上的属性指定一个getter和setter函数,在getter和setter函数内部去操作(读/写)data中对应的属性
// 简化版代码示例
function Vue(options) {
this._init(options)
}
Vue.prototype._init = function(options) {
let vm = this // vm指向当前Vue实例
vm.$options = options // 把选项赋值给$options
let data = vm.$options.data // 获取选项里面的data
vm._data = data // 把_data指向data
for (let key in data) { // 遍历data里面所有属性
Object.defineProperty(vm, key, { // 给vm添加同名属性
get() {
return vm._data[key]
},
set(value) {
vm._data[key] = value
}
})
}
}
这样,当我们访问或修改vm.xxx时,实际上就相当于访问或修改了vm._data.xxx: 这就是Vue中数据代理的基本原理。
数据代理的好处
使用数据代理的好处有以下几点:
- 可以更方便地操作data中的数据,而不需要每次都写this._data.xxx,而只需要写this.xxx就可以了。
- 可以在getter和setter函数中添加一些逻辑,比如通知视图更新,执行一些回调函数等。
- 可以实现数据的双向绑定,即当数据变化时,视图也会随之变化;当视图变化时,数据也会随之变化。