Vue2响应式原理(二)数据代理

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做到的



总结

  1. Vue中的数据代理:通过vm对象来代理data对象中的属性的操作(读 / 写)
  2. Vue中数据代理的好处:更加方便的操作data中的数据
  3. 基本原理:
    (1)通过Object.defineProperty()把data中的所有属性添加到vm上
    (2)为每一个添加到vm上的属性,都指定一个 getter 和 setter
    (3)在getter 和 setter 内部去操作(读 / 写)data中对应的属性

响应式到此还没有讲完,后续会继续更新下一篇文章去继续讲解~

猜你喜欢

转载自blog.csdn.net/qq_42667613/article/details/123579381