破防!Vue2 响应式原理(Vue2必会)

73 阅读4分钟

大家好,我是大澈!一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员👨🏻‍💻,关注我,科技未来或许我能帮到你!

今天聊聊Vue生态前端一个老生常谈的问题,Vue2 响应式原理。

这个问题呢,是基础,也是重点。

网上有各种各样的理解,眼花缭乱。而这次,我会以一个全新的角度出发,主打一个简洁,通俗易懂。

话不多说,朋友们,开整!

一、重点描述

总的来说,Vue响应式设计,使得 Vue 能够在初始渲染时快速构建 DOM,而在数据更新时通过 diff 算法只更新实际变动的部分,从而提高了性能和响应速度。

所以,这里我把 Vue2 响应式原理,分为了2个阶段、5个步骤。

2个阶段:初始化阶段、数据更新阶段。

5个步骤:数据劫持、模板编译、虚拟 DOM 生成、虚拟 DOM 对比、DOM 更新。

5个步骤组合实现了2个阶段。

2个阶段分别对应了生命周期的创建、更新。

掌握了5个步骤后,组合起来就掌握了2个阶段,进而就掌握了Vue2实例的生命周期核心。

二、细节剖析

1、5个步骤

5个步骤:数据劫持、模板编译、虚拟 DOM 生成、虚拟 DOM 对比、DOM 更新。

1.1、数据劫持

在 Vue 实例创建时,数据劫持就开始执行。

Vue 遍历 data 中的所有属性,利用 Object.defineProperty 为每个属性设置 getter 和 setter。

当属性被读取或修改时,通过 getter/setter 拦截,实现对数据变化的监控。

1.2、模板编译

在数据劫持完成后,Vue 会将HTML模板转化为js渲染函数。

1.3、虚拟 DOM 生成

调用生成的渲染函数,会创建一个新的 watcher ,并根据当前的数据状态生成虚拟 DOM 树。

同时,渲染函数会访问数据属性,这时每个属性的 getter 会被触发,getter 内部会将当前渲染中的 watcher 添加到依赖列表中,建立数据与视图之间的关联。

此时,如果响应式数据发生变化,数据对应的 setter 会被触发。

setter 触发通知(如调用 dep.notify()),将依赖该数据的 watcher 加入更新队列。更新是异步批量处理的,避免频繁重渲染。

由于 watcher 被触发,渲染函数重新执行,同样会进行依赖收集,确保最新数据与视图绑定,最终生成新的虚拟 DOM 树。

1.4、虚拟 DOM 对比

如果有旧的虚拟 DOM,新旧虚拟 DOM 树通过 diff 算法进行比较,找出具体发生变化的部分。

1.5、DOM 更新

根据虚拟 DOM diff 得到的差异,进行 Patch 过程。

生成一个变更清单,记录所有需要修改的 DOM 节点,直接操作真实 DOM,但只修改变更清单中记录的部分,而不是整个页面重渲染,进而提高更新性能和页面响应速度。

此时,父组件更新时,子组件不会重新渲染,除非子组件使用的 props 发生变化。

当然,如果没有旧的虚拟 DOM,则无需进行 diff 对比,无需进行 Patch 过程,直接一次性生成完整的 DOM 结构。

2、2个阶段

2个阶段:初始化阶段、数据更新阶段。

1.1、初始化阶段

Vue 实例创建后首次渲染页面时的过程。

经历了4个步骤:数据劫持、模板编译、虚拟 DOM 生成、DOM 更新。

注意,这个阶段没有旧的虚拟 DOM,无需进行 diff 对比,无需进行 Patch 过程,直接一次性生成完整的 DOM 结构。

1.2、数据更新阶段

在数据发生变化后重新渲染页面的过程。

经历了3个步骤:虚拟 DOM 生成、虚拟 DOM 对比、DOM 更新。

注意,这个阶段是在响应式数据发生变化时,数据对应的 setter 会被触发,进而执行更新流程。

好了,今天要分享的内容就是这么多,最后感谢朋友们给个点赞、分享、推荐,拜拜~