什么是数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)。
想要更加深刻的理解什么是数据代理,就必须先了解JS中对象的一个方法:Object.defineProperty(),数据代理主要使用Object.defineProperty()的第三个参数中的setter和getter;对其不太了解的小伙伴可以看下小shy之前专门对Object.defineProperty()的讲解 Object.defineProperty()详解。
数据代理案例理解
举例:定义一个对象obj1,给obj1定义一个属性name,再定义一个对象obj2,想让obj2可以访问obj1中name的值,并且也可以修改obj1中的name。
代码如下:
const obj1 = { name: '孙悟空' };
const obj2 = {};Object.defineProperty(obj2, 'name', {// obj2访问obj1中name的值get() {return obj1.name;},// 修改obj1中name的值set(value) {obj1.name = value;}
})
效果如下:
访问数据:
修改数据:
Vue中的数据代理
vue中的数据代理原理和上述例子一样,也是使用了Object.defineProperty()来实现的,使用了其getter 和 setter。下面使用尚硅谷视频讲解来介绍下vue中是如何实现数据代理的。(如需观看视频可在b站搜索尚硅谷vue即可)
首先我们在data中定义一些数据
以下是vue文件
<template><div><h1>名称:{{name}}</h1><h1>地址:{{address}}</h1></div>
</template><script>
export default {components: {},data() {return {name: '尚硅谷',address: '北京'}},mounted() {console.log(this)},
}
</script>
我们在mounted中打印下this(vue实例对象),看看里面都有什么。
我们看到vue实例对象身上有这两个属性,但是一开始的状态是…(三个点),这三个点其实就表示的是该数据是通过Object.defineProperty()来创建的;当然在下面也可以看到name和address这两个数据的getter和setter。
不墨迹,直接开讲:
vue是怎么实现getter 和 setter的呢?
在data中定义name 和 address的时候有如下步骤:
- 在data中定义name 和 address的时候,vue实例对象在其自身添加了一个_data属性(可以理解为就是data),用来存储data中定义的name 和 address;
此时页面只能是通过_data.name的形式才能访问,但是上述代码并不是这样的,是直接访问vue实例对象中的name和address,有意思的来了; - 这时候vue会在该vue实例对象上开始加东西(会将data中定义的数据都加到vue实例对象中),首先会先加一个name属性,name的值则是通过getter来读取_data中name的值;如果修改vue实例对象中name的值,则通过setter映射到_data中的name来进行修改;
- 同理address也是如此,这种通过getter 和 setter将_data中的数据放到vue实例对象中即为数据代理。(目的就是想让开发者编码相对比较方便一些)
vue数据代理图如下
总结
1.Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:更加方便的操作data中的数据
3.基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm (vue实例对象)上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。
问题
首先我们先看下_data中是什么样的。
我们会发现,_data中也存在数据代理,其实这里面并不是数据代理,而是数据劫持;其实这样做是为了实现响应式,当你修改了vue实例对象中的数据的时候,此时_data中的数据也随之发生了改变,页面中用到该数据的地方则会自动更新,如果想要实现这种效果,就需要让vue知道_data中的数据发生了改变,数据劫持就是来干这个事情的;这里先简单说下,后续会专门出一片文章来解释。