1、什么是数据代理
数据代理就是 通过一个对象代理对另一个对象中属性的操作(读 / 写)
举例说明: 有一个对象 obj ,obj上有一个属性x,以后我想访问这个x,直接obj.x访问即可,想修改obj.x也是非常容易。但是此时我还有一个对象 obj2,我希望这个obj2 也可以访问和修改 obj 身上的 x。那么这就是通过一个对象 obj2 代理对另一个对象 obj 中属性的操作。
接下来我们来实现上述的需求:
let obj = { x: 100 };
let obj2 = { y: 200 };
Object.defineProperty(obj2, "x", {
get() {
return obj.x;
},
set(value) {
obj.x = value;
},
});
这样就完成了obj2对obj.x的访问和修改。
注: Object.defineProperty的详细讲解在我上一篇文章
展开x:
以上就是数据代理,通过对象 obj2 代理对 对象 obj 中属性的操作。
2、vue中的数据代理
写段代码:
<script src="../js/vue.js"></script>
<div id="root">
<h2>姓名: {{name}}</h2>
<h2>住址: {{address}}</h2>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
// 没用vue-cli,这里的data可以不用写成函数
data: {
name: "张三",
address: "中国",
},
});
</script>
我们看一下vm的值:
上图中用红框框起来的两个属性有没有觉得特别的熟悉,没错,这就是咱们前面讲到的。也就是说,vm身上有的address和name这两个属性都是通过Object.defineproperty加上去的。当有人访问vm身上的name的时候,getter开始工作,若是通过vm去修改这个name的时候,setter开始工作。这两个属性都有自己的setter和getter。
这里有代理存在,这里的address和name 代理对data 中的 address和name的操作。也就是说,我们修改这个vm上的address,实际上是修改的我们写的data中的address,接下来我们去验证这个代理关系。
猜想一:当我们读取vm上的address时,getter工作,去读取data上的address。当我们修改vm上的address时,setter工作,去修改data上的address
验证 getter:
我们可以看到,vm.address 会随着 data中的address改变而改变。getter验证成功
验证 setter:
我们把vm.address修改以后,怎么知道data中的address改没改呢,我们可以这样写:
把data定义一个变量,提取出去,这样全局里面就有一个data了
上图可以得出 setter验证成功
其实vm拿到了我们所写的data,并且存到了自身,不过名字不是叫data,而是 _data:
而且我们可以验证一下:
到此为止,我们就验证了猜想一:代理
一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新
我们在控制台直接修改 vm.address 后页面会发生变化。
原因:修改vm.address,setter调用,data中的address被修改,data中的数据被修改,页面用到该数据的地方自动刷新。
假如vue没有数据代理,那么vm身上没有直接的address,那么我们在模版中用数据的时候只能这么写:
页面上也是可以正常显示的,模版中可以直接写 _data.address的原因是:vm身上以及vue原型对象上的所有的属性和方法在模板中可以直接用。
但是如果我们每一个地方都写_data.xxx, 程序员就疯掉了,所以数据代理把data中的数据在vm身上放了一份,为了编码更方便。没有数据代理不是不能写代码,也可以写,只不过麻烦,每一个用到的地方前面都要加 _data。
我们要知道:虽然模版中直接写了 address,但其实他是通过getter读取了 _data里的address
vue2中的数据代理是通过Object.defineProperty做到的
总结
- Vue中的数据代理:通过vm对象来代理data对象中的属性的操作(读 / 写)
- Vue中数据代理的好处:更加方便的操作data中的数据
- 基本原理:
(1)通过Object.defineProperty()把data中的所有属性添加到vm上
(2)为每一个添加到vm上的属性,都指定一个 getter 和 setter
(3)在getter 和 setter 内部去操作(读 / 写)data中对应的属性
响应式到此还没有讲完,后续会继续更新下一篇文章去继续讲解~