前言: 不知道大家在学习vue的时候,有没有这些疑问。什么是数据的双向绑定?vue是如何检测到我的数据改变了呢?vue中到底是怎么实现数据改变,模板就会重新解析的呢?为什么数组的更新数据方式和对象不同呢?多交流,少疑惑。在这里,我想和大家分享一点我学习到的和一些理解。如果有不足之处还希望能够指点。
数据代理
一、什么是数据代理
在Vue中,其实有很多运用到了数据代理的地方,所谓代理,可以理解成一个中间商(Vue),你把产品(数据) 交由她托管,当客户想要查询商品价格(想要访问数据) 时,中间上就会找到你去询问价格,然后把结果展示给客户。其实这就是一个简单的代理。那么这个逻辑在Vue中是如何实现的呢?
二、数据代理简单原理
大致理解代理后,想要理解Vue中的数据代理,就要先提到一个很重要的API “Object.defineProperty()”。不知道小伙伴们还是否熟悉它的用法(不熟悉的速速百度)。他有三个参数,Object.defineProperty(property,'attribute',{options}),第一个是指哪一个对象,第二个是指要代理的属性,第三个就是配置项。Vue实现数据代理的方法其实就是大量运用了该方法。配置项的其他内容在这里就不说了,主要说一下get()和set()方法。假设此时有一个需求:
``
动态的将
num的值赋值给小红的age属性
//此时,有的同学可能就会想到可以这样写
let num = 18
let person = {
name: '小红',
age: num
}
//{name:"小红","20"}
“ 这么做雀氏将
num的值赋给了age,但是他不是动态的,此时如果更改num的值,age是没有反应的 ”
“ 所以此时我们要用到
Object.defineProperty:”
let num = 12
let person = {
name: '小红',
}
Object.defineProperty(data,"age",{
// value:20,
// enumerable:true, //是否枚举
// configurable:true, //是否可删除
// writable:true //可修改的
get(){
console.log("有人读取了当前的num值") //get()的作用就是,当有人读取了age属性时,get()就会被调用
return num
}
})
“ 这时候就会发现这个
age变得有点不一样 "
⭐ “为什么这个age后面变成(...)了?” 其实这个就相当于是代理了,我们不去询问(点击)的时候,
person不会告诉我们age是多少,当我们想访问(点击...)的时候,就会触发age的get(其实就是叫getter)方法,然后get方法返回num的值作为age的value。这样,当num改变时,我们就能动态获取num的值啦!
那么接下来同理,有
getter,就会有setter,顾名思义,setter就是当有人想改变peroson中age的值时就会被调用。此时重新有个新需求,我想吧age的年龄值改成100,肯定会有小伙伴想到这样写:
person.age = 100 //我们来看一下结果
⭐ 这时发现age的值依旧是12,刚刚明明修改过了age的值了啊?? 其实原因很简单,我们的age它的值是只和num有关的,因为我们访问age时,他总返回的是
num的值,num不变,age就不会变的。“这简单,那我把num的值一改不就得了”。肯定会有小伙伴有这样的想法吧😏~。在这里,既然我们呢选择了代理,那我们就不需要去直接修改源数据。(也可以理解成我们自己改商品价格就行,不用问你了),那么看接下来的操作:
let num = 12 //对象1
let person ={ //对象2 也即是对象2代理了对象1中的num
name:"小红",
age:num
}
Object.defineProperty(person,"age",{
// value:20,
// enumerable:true, //是否枚举
// configurable:true, //是否可删除
// writable:true //可修改的
get(){
console.log("有人读取了当前的num值") //当有人读取了age属性时,get()就会被调用
return num
},
set:function (value){ //set(){}是简写形式
console.log("有人修改了当前age的值")
//当有人修改了age时,set就会被调用,并且set(value)还可以收到修改的值是多少
num = value //将新的值赋值给num,这样就实现了一个类似于双向的绑定!
}
})
" 这时候,我们再去修改age的值!!"
"发现age的值变了!!"
到这里,大家有没有嗅到一点vue中监测数据变化的味道呢😏?接下来我们就看一看vue中的数据监测和代理是怎样的~
三、Vue中的数据代理
先看如下代码:
...
<div id="root">
<h1>姓名:{{name}}</h1>
<h1>年龄:{{age}}</h1>
</div>
...
const vm = new Vue({
el:"#root", //vue中的数据代理
data:{
name:'小花',
age:20
}
})
//看效果
这时候,我们看先一下
Vue的实例对象,vm身上有什么东西
vm身上有很多属性和方法,但其中有两个属性我们很眼熟,这不就是我们刚刚写的东西吗?再点看一下
到这里,其是这个就是**
vue中的数据代理**了,同样他也有getter和setter
此时,如果我们更改
age的值,vue就对界面重新解析
我们还可以通过另一种方式去修改age的值。大家仔细观察的话,vue的身上有一个_data对象,里边的内容和我们写在data中的数据内容是一样的。
如果我们这样修改:
vm._data.age = 30
我们发现,age也被修改了。到这里,我们其实就发现了他监测数据改变的原理了。这里我给大家做一个总结。
总结 其实vue在这里做了一件很聪明的事。 在这里,
vm拿到data中的数据后,放在了vm里的_data中。实际上data就是_data。vm中的age代理了_data中的age。读取vm.age时,调用get方法,读取了_data中的age。修改了vm中的age时,就会调用set方法去修改_data中的age。估计会有人想为什么要多此一举呢?其实,如果不做代理,那么在“{{ }}”中就要这样写了“{{_data.xxx}}”,会很麻烦。如果想要验证_data是否等于data。可以这样验证。
vm._data === options.data(options指的是当时new Vue时候的配置对象,也就是()里的)
//true
图例分析
好啦,分享就暂时到这里啦,主要还是偏新手向,有不足的地方欢迎指点~