数据响应式原理到底是个啥?

166 阅读4分钟

最近面试的时候,老是被问到vue的双向绑定原理(数据响应式原理)是啥? 虽然背了八股文,但脑子还是一团浆糊,所以花了点时间找个基础视频搞清楚。现记录下:

1:get和set干嘛的?

常规的,我们使用对象调用函数一般是这种形式:

image.png

但其实还有一种不用括号的函数调用形式,那就是get

image.png

那既然有get获取,肯定就有set修改了。

image.png

如图可知,这里就是通过这样的赋值方式去调用set,然后使用set修改对象原本的属性
那这里有个问题,姓名这东西是对象里的一个属性吗? 我们不妨打印出来看看;

image.png

可以看到,打印结果中只将姓和名认为是属性,而姓名:{...} 这个写法表示可以通过get,set来对属性“姓”和“名”进行读写操作,但实际并不存在这个属性;

了解完get和set之后,再看下Object.defineProperty是个啥东西?

2:Oject.defineProperty

前面的例子中我们都是在定义对象时给它加的一些属性和函数,那么假如我对象都定义完了,我在后面的代码里咋给它添加get/set ??
这就需要Oject.defineProperty这个工具人上线了,直接像下面这样简单粗暴加上即可~

image.png

Oject.defineProperty 就这点功能了吗? No,No,No, 它就是一块砖,还需要搬到更重要的地方,接着往下看

3:代理和监听

前面说到get/set可以完成数据的读写,但简单的读写我直接写成obj.xxx=xx 的形式不就行了吗?为何还要大费周章的写那么多代码?
好,为了平复你的心情,我们看看set其实还可以做更多的事情,就是在你修改数据时给你找点门槛,别动不动就对我的数据动手动脚,不满足条件就不能修改。如图:

image.png

这样就万无一失了么?
嘿嘿,我为啥要跟着你的步骤去改?我把你一开始初始的数据改了,你能奈我何?

image.png emm,好吧,着实难受,没想到这一层,那有没有啥办法不让他直接修改我的原数据?
那就让代理来试试吧。

3.1:代理

为了更好理解这个概念,大家可以想象自己租房的场景,租房都有个中介,他来代理房东跟我们交涉租房的事情,我们跟中介说的话,中介都一五一十的告诉给了房东。
那在代码里我也弄个代理,让你修改数据都通过代理来操作,代理改数据,那我原数据也得到了修改。但你因为没有我原数据的操作接口,就不会出现之前那种你可以擅自修改我原数据的情况了。看你还嘚瑟?

image.png

3.2:监听

我有一个要求,就是确保所有的属性的读写操作都通过我的get/set来实现,经过上面的步骤看起来应该万无一失了,但好像还是漏了一种情况。
有些人可能就是有个性,我不喜欢把数据直接写到括号里,我定义个变量来存着它不行么?像下面这样:

image.png

这么一看,还是有个漏网之鱼出现了。那我如何让这样的修改也不允许呢?
那就再给一开始的属性加个代理。

image.png 上图新增的代码就是将data的name(其实也就是myName的name) 转换成get/set类型。这样即使你又手痒直接myName.name='xxx' 也还是需要经过我的代理才能实现功能。这样一来从头到尾你对数据的一举一动都在代理的掌控之中,是不是就像被监听了起来?

而这个也就是vm=new Vue({data:{myData}})的原理。 vm就是myData的代理,对myData的所有属性进行监听,来确保vm不会漏掉页面中的数据改变。所以Vue所做的操作就是,当我监听到你的数据改变时,那我给你一个回应=>去完成页面的渲染。 这种有来有回的响应操作,即数据响应式


花了1h写完这篇文章,本来觉得自己清楚的概念要写成文章解释给别人听还是需要进一步的概念加工和理解,也容易发现很多自己知识漏洞的地方。输出确实是一种比较好的既提升自己学习效果,也有可能对别人有帮助的一个方式。 当然,本文还有很多疏漏的地方,希望大家批评指正