1.JS中的Object.defineProperty
在理解数据代理之前先看一个例子,有助于理解
定义一个变量和对象,如果想要给person对象添加一个属性 number,并且是直接利用现有的这个number,而且还能监测到number的变化,如果有变,则person中的number也跟着改变,当我们修改person中的age时,number也会跟着改变,该如何实现?
let number = 18
let person = {
name:'张三',
sex:'男',
}
此时可以采用Object.defineProperty(obj,‘prop’, descriptor),其中obj是目标对象,即我们要对哪个对象进行操作,'prop'是属性名,descriptor是配置项,里面有若干项可以进行设置,具体用法如下:18
//给person对象添加了age属性,在配置项里面规定了age的值为18
Object.defineProperty(person,'age',{value:18})
当然,配置项里面不仅有value,其他的如下:
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
}
})
这里面的get和set是相当重要的,
get(){} 函数,当person中的age属性被读取时被调用,我们可以提前写好return来规定返回值;
set(){}函数,当person中的age属性被修改时被调用,并且要传入参数,即修改后的新值;
回到一开始的那个问题,我们想要person中的age始终紧跟着number的值,并且还能实现
读、改person中的age,且number也会变,写法如下:
//访问person中的age时,直接返回number,此时实现了读取age时拿到和number同步的值
get(){
console.log('有人读取age属性了');
return number;
}
在控制台实现如下:
接着是set
//当修改person中的age时,新修改的值传来,赋给value,我们直接把value赋值给number
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
此时number的值就变成了我们想要修改的新值,当我们用person.age去访问修改后的值时,其实返回的就是这个最新的number,实现了同步,控制台操作如下:
一开始输出person,其中的age和初始的number一样,是18;
然后直接通过person.age = 99来修改值 ,修改之后打印number发现已经同步了,然后再次打印person.age,已经实现了修改。
看完这个小例子,我们来个更简洁的例子理解数据代理
2.数据代理小例子
数据代理,通过一个对象代理对另一个对象中属性的操作,这里我们想让对象obj2来操作(读写)obj1中的属性,这就是数据代理。实现过程如下:
let obj1 = { x: 100 };
let obj2 = { y: 200 };
//我们想让obj2 能够访问、读写obj1中的属性,即obj2代理了obj1 来进行原本属于obj1的各种操作,
//写法如下:
Object.defineProperty(pbj2, 'x',
{
//读取obj2中X的时候,我们让它读取到obj1的X
get() {
return obj1.x;
},
//修改obj2中X的时候,让传来的新值直接赋给obj1的x
set(value) {
obj1.x = value;
}
})
以上小例子很清晰地展示了数据代理的过程,
下面我们要引出本文的最终目的,理解Vue中的数据代理
3.Vue中的数据代理
先定义一个Vue实例vm,初始化2个数据
const vm = new Vue({
el: '#root',
data: {
name: '尚硅谷',
address: '宏福科技园'
}
})
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性