前端面试系列【016】 - 说一说你对 vue 响应式的理解?

323 阅读3分钟

这个问题现在都快被问烂掉了,相信大家或多或少都有自己的理解。

这里将从以下的角度来进行回答:

  • 什么是数数据响应式?
  • 为什么需要响应式?
  • 它解决了什么问题?
  • vue 2.x 中的响应式原理
  • vue 3 中响应式的变化

在回答之前,可以看一看我之前写的数据响应式

那么下面便开始回答吧~

什么是数据响应式?

所谓数据响应式,其实关键就在这个响应二字:能够检测数据的变化,当数据发生变化的时候,能够做出对应的响应,这就是数据响应式了。

为什么需要数据响应式?

我们都知道,一个框架、模式或者算法的出现,一定是为了解决工作中的痛点。

数据响应式也不例外,它的出现是为了解决前端开发中,开发者需要关注数据如何变化,又需要关注视图如何更新,从而导致开发难度高,维护成本高的问题。

它解决了什么问题?

做为胶水层,它解决了开发者需要兼顾视图与数据的问题。

数据响应式的出现,让用户在开发的时候,只需要关注业务逻辑,更细数据即可,而随后的 DOM 操作,视图更新则完全不必关心,这些都将有框架解决。

这极大地提升了开发效率降低了开发难度

vue 2.x 中的响应式原理

总所周知,vue 2.x 中实现数据响应式的核心 api 是 Object.defineProperty

它的整个实现流程大致如下:

  • initState 开始,处理 data 的方法为 initData
  • initData 中调用 observe 做响应式处理
  • observe 中会 new Observer 进入到响应式和核心部分
  • 如果被处理的对象是数组,则先覆盖其数组原型的方法,然后 observe 其元素
  • 覆盖方法在 methodsToPatch,这是一个工厂,先执行原始方法,然后进行扩展,最核心的是调用了 ob.dep.notify() 通知视图更新
  • 如果目标是纯对象,则在 walk 中遍历
  • walk 会调用 defineReactive 用于实现响应式
  • 如果被定义的目标是对象,则会递归查找到最深的子元素
  • defineReactive 中的核心方法为 Object.defineProperty
  • 在 get 中进行依赖收集
  • 在 set 中通过 dep.notify() 通知 Wather 更新视图

那么上面的流程,有什么局限性吗?

事实上是有的:

  • 如果需要在对象中元素有变动,则需要使用额外的 api:set/delete
  • 无法实现对 ES6 中新增数据类型的响应式,如 Set, Map

vue 3 中响应式的变化

关于这一点,尤大大多次的演讲都有提到,这里推荐大家去小破站搜一搜,相关视频非常多。

  • 首先 vue 3 中实现响应式的核心 api 改为了 ES6 中新增的 Proxy
  • 相比于递归遍历目标对象所有元素,Proxy 则是相当于在对象外层套一个壳子,这样性能要高能多(不用递归,不用开辟大量内存空间存储依赖关系)
  • vue 3 中的响应式作为一个模块独立出来了,完全可以在不引入 vue 的情况下使用

结语

更佳阅读体验:016 - 说一说你对 vue 响应式的理解?