首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Vue.js技术揭秘-派发更新

派发更新

通过上一节分析我们了解了响应式数据依赖收集过程,收集的目的就是为了当我们修改数据的时候,可以对相关的依赖派发更新,那么这一节我们来详细分析这个过程。

我们先来回顾一下 setter 部分的逻辑:

setter 的逻辑有 2 个关键的点,一个是 ,如果 为 false 的情况,会对新设置的值变成一个响应式对象;另一个是 ,通知所有的订阅者,这是本节的关键,接下来我会带大家完整的分析整个派发更新的过程。

过程分析

当我们在组件中对响应的数据做了修改,就会触发 setter 的逻辑,最后调用 方法,它是 的一个实例方法,定义在 中:

这里的逻辑非常简单,遍历所有的 ,也就是 的实例数组,然后调用每一个 的 方法,它的定义在 中:

这里对于 的不同状态,会执行不同的逻辑, 和 等状态的分析我会之后抽一小节详细介绍,在一般组件数据更新的场景,会走到最后一个 的逻辑, 的定义在 中:

这里引入了一个队列的概念,这也是 Vue 在做派发更新的时候的一个优化的点,它并不会每次数据改变都触发 的回调,而是把这些 先添加到一个队列里,然后在 后执行 。这里有几个细节要注意一下,首先用 对象保证同一个 只添加一次;接着对 的判断,else 部分的逻辑稍后我会讲;最后通过 保证对 的调用逻辑只有一次,另外 的实现我之后会抽一小节专门去讲,目前就可以理解它是在下一个 tick,也就是异步的去执行 。接下来我们来看 的实现,它的定义在 中。

这里有几个重要的逻辑要梳理一下,对于一些分支逻辑如 组件相关和之前提到过的 钩子函数的执行会略过。

队列排序 对队列做了从小到大的排序,这么做主要有以下要确保以下几点:1.组件的更新由父到子;因为父组件的创建过程是先于子的,所以 的创建也是先父后子,执行顺序也应该保持先父后子。2.用户的自定义 要优先于渲染 执行;因为用户自定义 是在渲染 之前创建的。3.如果一个组件在父组件的 执行期间被销毁,那么它对应的 执行都可以被跳过,所以父组件的 应该先执行。

队列遍历在对 排序后,接着就是要对它做遍历,拿到对应的 ,执行 。这里需要注意一个细节,在遍历的时候每次都会对 求值,因为在 的时候,很可能用户会再次添加新的 ,这样会再次执行到 ,如下:

可以看到,这时候 为 true,就会执行到 else 的逻辑,然后就会从后往前找,找到第一个待插入 的 id 比当前队列中 的 id 大的位置。把 按照 的插入到队列中,因此 的长度发生了变化。

状态恢复这个过程就是执行 函数,它的定义在 中。

逻辑非常简单,就是把这些控制流程状态的一些变量恢复到初始值,把 队列清空。接下来我们继续分析 的逻辑,它的定义在 中。

函数实际上就是执行 方法,并传入 的回调函数。 函数逻辑也很简单,先通过 得到它当前的值,然后做判断,如果满足新旧值不等、新值是对象类型、 模式任何一个条件,则执行 的回调,注意回调函数执行的时候会把第一个和第二个参数传入新值 和旧值 ,这就是当我们添加自定义 的时候能在回调函数的参数中拿到新旧值的原因。那么对于渲染 而言,它在执行 方法求值的时候,会执行 方法:

所以这就是当我们去修改组件相关的响应式数据的时候,会触发组件重新渲染的原因,接着就会重新执行 的过程,但它和首次渲染有所不同,之后我们会花一小节去详细介绍。

总结

通过这一节的分析,我们对 Vue 数据修改派发更新的过程也有了认识,实际上就是当数据发生变化的时候,触发 setter 逻辑,把在依赖过程中订阅的的所有观察者,也就是 ,都触发它们的 过程,这个过程又利用了队列做了进一步优化,在 后执行所有 的 ,最后执行它们的回调函数。 是 Vue 一个比较核心的实现了,下一节我们来重点分析它的实现。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230118A01JBN00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券