05.数据代理

104 阅读3分钟

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;
}

在控制台实现如下:

1655956024060.png

接着是set

//当修改person中的age时,新修改的值传来,赋给value,我们直接把value赋值给number
set(value){
    console.log('有人修改了age属性,且值是',value)
    number = value
}

此时number的值就变成了我们想要修改的新值,当我们用person.age去访问修改后的值时,其实返回的就是这个最新的number,实现了同步,控制台操作如下:

1655956676415.png

一开始输出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: '宏福科技园'
        }
    })

1656055157762.png

1.Vue中的数据代理:

通过vm对象来代理data对象中属性的操作(读/写)

2.Vue中数据代理的好处:

更加方便的操作data中的数据

3.基本原理:

通过Object.defineProperty()把data对象中所有属性添加到vm上。

为每一个添加到vm上的属性,都指定一个getter/setter。

在getter/setter内部去操作(读/写)data中对应的属性