vue2生命周期和响应式原理

847 阅读4分钟

响应式原理

什么是响应式原理?

所谓响应式原理,就是当data中的变量发生变化时,vue能够监听到,并且做些什么事情

vue如何监听变量的变化?

在vue2中,响应式背后的原理其实是使用Object.defineProperty对data选项中的变量进行“劫持”,所谓的劫持就是递归遍历data对象,拿到里面的变量,为每个变量添加getter和setter拦截器(钩子)。

当我们通过vue指令使用这些变量的时候(也就是对变量进行getter访问),vue会进行依赖的收集(相当于记录在模板中的那些DOM上使用了这些变量,并为这些DOM添加更新函数),依赖收集完成之后,会通知Watcher进行视图更新。

当我们更新变量的时候,会触发setter钩子,之后通知Watcher,Watcher根据依赖收集在使用了这个变量的地方进行视图更新。

data.png

生命周期

概念:

vue的生命周期就是一个vue组件从创建到销毁的过程。我们可以类比成一个人从出生到死亡的过程。 vue的生命周期函数总共有11个,常用的有8个,这些生命周期函数会在vue组件生命周期到达对应时刻被回调

vue的生命周期有四个阶段,分别对应两个生命周期函数(常用的8个):

第一阶段(创建阶段): beforeCreate、created

第二阶段(挂载阶段): beforeMount、mounted

第三阶段(更新阶段): beforeUpdate、updated

第四阶段(销毁阶段):beforeDestroy、destroyed

理解:

把每个生命周期函数的回调理解成一个人在生命中某个时刻的记录。始终记住一个点,生命周期函数回调只是某一个时刻,而不是某一个阶段。

做了哪些事:

在beforeCreated时刻之前:

初始化methods中的方法和初始化生命周期函数

beforeCreated时刻和created时刻之间:

对data中的变量进行数据劫持,所谓数据劫持,就是递归循环data,使用Object.defineProperty为其中的每个变量添加getter/setter拦截器(钩子)。 并且将它们绑定到组件实例上(绑定this值,这说明created阶段就可以访问到data中的变量了)。

created时刻和beforeMount时刻之间:

查看是否有el属性和template属性,如果有,就把对应的template模板编译成render函数 , 如果没有,就会尝试把el的父元素作为模板进行编译。

beforeMount时刻和mounted时刻之间:

根据render函数,生成抽象语法树(AST),再根据AST生成虚拟DOM(VNode),虚拟DOM是对真实DOM的一种数据描述,本质上是json文件,存在于我们电脑的内存中。

之后再根据虚拟DOM生成真实DOM(这个过程有依赖收集、Watcher,也就是响应式在这里工作),把声明式变量替换成真实数据,DOM渲染完成,(这意味着要想操作DOM,最早可以在mounted函数中)

mounted时刻到beforeUpdate时刻之间:

这里说时刻就显得有点牵强,简单来说就是数据发生变化时,这是一个循环过程,因为数据在不断的变化。

beforeUpdate时刻到updated时刻之间:

每当有数据发生变化时,render函数就会重新渲染新的虚拟DOM,此时有新旧虚拟DOM,之后使用大名鼎鼎的Diff算法,进行新旧虚拟DOM的对比,寻找它们之间的差异,再通知Watcher,根据依赖收集再次更新真实DOM。

beforeDestroy时刻和destroyed时刻之间

拆卸Watcher、子组件和事件监听

lifecycle.png

思考:

1.Diff运算进行新旧Vnode的对比,找出它们之间的最小差异(怎么找差异呢?)

2.生成虚拟DOM浪费时间,为什么还要生成虚拟DOM?

虚拟DOM存在的价值: 大大的降低了人为更新DOM的代价,最小化的更新DOM,尽可能的减少了DOM操作,避免了“滥杀无辜”

总结:

实际开发中并不会都用这些生命周期函数,最常用的有三个:created、mounted、beforeDestroy

created里面一般调用接口,建立长连接,

mounted里面也可以调用接口,建立长连接,开启定时器,执行一些DOM操作,

beforedDestroyed里面可以关闭长连接,关闭定时器,清除缓存数据。