Vue中的数据代理

要理解vue中的数据代理,我们需要先理解defineProperty方法,再理解数据代理的含义,最后我们再来看vue中的数据代理

Object.defineProperty方法

最基础的用法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
  <title>Title</title>
</head>
<body>
  <script>
    let num = 18;
    let person = {
      name:'zhouzhou',
      sex:'male'
    }
  //  最基础用法
  //  给person对象添加一个属性age,我们可以使用Object.defineProperty方法
  //  传入三个参数,第一参数为对象名,第二个要添加的属性名,第三个参数为一个对象,可以在其中定义要添加的属性的值和特性
    Object.defineProperty(person,'age',{
      value:'21'
    })
  </script>
</body>
</html>

我们输出这个person对象发现,我们通过defineProperty添加的age属性,颜色和直接添加的属性不太相同,为淡粉色

淡粉色的含义为:不可枚举

我们知道,我们通过Object.key或者foreach可以枚举出对象中的全部属性

枚举person对象后我们发现,没有age这个属性

原因是,我们通过Object.defineProperty给person添加的元素默认是不可枚举的

如果想让其可以枚举,我们可以在传入的第三个属性(对象类型的)中添加设置

除了这一点,我们还可以设置age属性的其他特性

来看下面一个例子:

我们申明了一个变量num,并且设置person属性中age的值为num

思考一个问题:age的初始值为多少呢?

我们可以在控制台中查看

再思考一个问题:修改num的值, age的值是否会改变呢?

我们发现,age的值并不会随着num的值的改变而改变,因为age = num只执行了一次

如果我们想做到修改num,age的值就随之修改,该怎么办呢?

我们可以使用上面说的Object.defineProperty来解决这个问题

被称为get函数(getter)可以简写成下面这种形式

如果打印person对象,我们就会发现,age:(...)这是因为,如果要查看其值我们需要调用getter

如果我希望修改person.age之后,num就发生变化,我们可以使用setter

数据代理

什么是数据代理?有两个对象,通过一个对象代理另一个对象中属性的操作(读/写)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
  <title>Title</title>
</head>
<body>
<!--什么是数据代理?有两个对象,通过一个对象代理另一个对象中属性的操作(读/写)-->
<script>
  let obj1 = {
    name:''
  }
  let obj2 = {}
  Object.defineProperty(obj2,'x',{
    //通过getter,访问obj2的x属性的时候,显示obj1的name属性
    get() {
      return obj1.name
    },
    //通过setter,修改obj2的x属性的时候,也修改obj1的name属性
    set(v) {
      obj1.name = v
    }
  })
</script>
</body>
</html>

vue中的数据代理

还记得MVVM模型吗?其中我们的第一个m(model)部分为

通过vm,我们最后会在V(视图)中访问到data这个对象

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
  <title>Title</title>
</head>
<body>
<script src="../js/vue.js"></script>

<div id="app">
    目前的数据:{{message}}
</div>

<script>
    const vm = new Vue({
        el:'#app',
        data:{
            message:'hello'
        }
    })
    console.log(vm);
  
</script>
</body>
</html>

首先我们观察vm这个Vue实例


我们可以发现:

  • 这个vm上出现了message属性,并且多了get/set message方法
  • 从这点我们可以看出message是通过defineProperty加上去的
  • 我们在data中定义了message属性,并且在vm上发现了它,而且使用了defineProperty方法

那么我们就可以猜想:这里是不是使用了数据代理了呢?通过vm代理了data?

接下来我们验证我们的猜想:

  • 如果修改options.data中的message,vm中message发生改变,那么证明了getter生效
  • 如果修改vm中的message,options.data中的message发生改变,那么证明了setter生效

验证getter是否生效很简单:改一下data中的数据,看看vm.message是否变化就完事了

我们发现,在代码中修改options.data中数据的数据从hello->hello123,再查询vm.message值为hello123,就说明,vm中的getter方法,可以查询到options.data中的数据

再验证setter方法是否生效:思路是修改vm.message,看看options.data中的数据是否修改,为此我们要想办法查看options.data中的数据,但是我们发现我们并不能直接获取到options.data,可是options.data必然存放在某个地方,那么options.data中的数据在什么地方呢?我们可以观察到,vm中有_data这一个属性,我们猜想这是options.data存放的地方,我们需要验证一下:

我们将代码变成这种格式,定义一个data对象,在vue的配置对象中让data:data(我采用es6的简写形式,我们称这个为options.data),这么做是为了方便拿到data,如果不这么写,我们发现我们无法拿到options.data,这么写了之后,options.data=data,我们要验证vm._data?=options.data只需要验证,vm._data?=data即可

输入控制台验证:

我们发现是相等的,我们可以得出结论:vm._data = options.data

那么我们接下来就可以修改vm.message的属性,修改完成之后,我们发现vm._data.message也被修改了,那么根据我们上面的出来的结论:options.data中的message也被修改了

以上论证完成

我们结论是:vm代理了vm._data而vm._data又等于options.data

好了,那么我们上面论证了半天的这个数据代理,我们使用Vue的时候如何体现呢?

最直观的体现就是当我们在页面上使用插值语法等的时候,我们可以直接拿到options.data中的数据,而不用使用_data.message这样的形式获得,目的就是让你写代码的时候少写点字

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值