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

Vue.js技术揭秘-组件更新

组件更新

在组件化章节,我们介绍了 Vue 的组件化实现过程,不过我们只讲了 Vue 组件的创建过程,并没有涉及到组件数据发生变化,更新组件的过程。而通过我们这一章对数据响应式原理的分析,了解到当数据发生变化的时候,会触发渲染 的回调函数,进而执行组件的更新过程,接下来我们来详细分析这一过程。

组件的更新还是调用了 方法,我们再回顾一下这个方法,它的定义在 中:

组件更新的过程,会执行 ,它仍然会调用 函数,在 中定义:

这里执行 的逻辑和首次渲染是不一样的,因为 不为空,并且它和 都是 VNode 类型,接下来会通过 判断它们是否是相同的 VNode 来决定走不同的更新逻辑:

的逻辑非常简单,如果两个 的 不相等,则是不同的;否则继续判断对于同步组件,则判断 、、 类型等是否相同,对于异步组件,则判断 是否相同。

所以根据新旧 是否为 ,会走到不同的更新逻辑,我们先来说一下不同的情况。

新旧节点不同

如果新旧 不同,那么更新的逻辑非常简单,它本质上是要替换已存在的节点,大致分为 3 步

创建新节点

以当前旧节点为参考节点,创建新的节点,并插入到 DOM 中, 的逻辑我们之前分析过。

更新父的占位符节点

我们只关注主要逻辑即可,找到当前 的父的占位符节点,先执行各个 的 的钩子函数,如果当前占位符是一个可挂载的节点,则执行 的 钩子函数。对于这些钩子函数的作用,在之后的章节会详细介绍。

删除旧节点

把 从当前 DOM 树中删除,如果父节点存在,则执行 方法:

删除节点逻辑很简单,就是遍历待删除的 做删除,其中  的作用是从 DOM 中移除节点并执行 的 钩子函数,并对它的子节点递归调用 函数; 是执行 的 钩子函数以及 的 钩子函数,并对它的子 递归调用 函数; 就是调用平台的 DOM API 去把真正的 DOM 节点移除。

在之前介绍组件生命周期的时候提到 这两个生命周期钩子函数,它们就是在执行 过程中,执行了 的 钩子函数,它的定义在 中:

当组件并不是 的时候,会执行 方法,然后就会执行 两个钩子函数。

新旧节点相同

对于新旧节点不同的情况,这种创建新节点 -> 更新占位符节点 -> 删除旧节点的逻辑是很容易理解的。还有一种组件 的更新情况是新旧节点相同,它会调用 方法,它的定义在 中:

的作用就是把新的 到旧的 上,这里我们只关注关键的核心逻辑,我把它拆成四步骤:

执行 钩子函数

当更新的 是一个组件 的时候,会执行 的方法,它的定义在 中:

方法就是拿到新的 的组件配置以及组件实例,去执行 方法,它的定义在 中:

的逻辑也非常简单,由于更新了 ,那么 对应的实例 的一系列属性也会发生变化,包括占位符 的更新、 的更新, 的更新, 的更新等等。

执行 钩子函数

回到 函数,在执行完新的 的 钩子函数,会执行所有 的 钩子函数以及用户自定义 钩子函数,对于 的钩子函数,之后我们会有具体的章节针对一些具体的 case 分析。

完成 过程

如果 是个文本节点且新旧文本不相同,则直接替换文本内容。如果不是文本节点,则判断它们的子节点,并分了几种情况处理:

与 都存在且不相同时,使用 函数来更新子节点,这个后面重点讲。

2.如果只有 存在,表示旧节点不需要了。如果旧的节点是文本节点则先将节点的文本清除,然后通过 将 批量插入到新节点 下。

3.如果只有 存在,表示更新的是空节点,则需要将旧的节点通过 全部清除。

4.当只有旧节点是文本节点的时候,则清除其节点文本内容。

执行 钩子函数

再执行完 过程后,会执行 钩子函数,它是组件自定义的钩子函数,有则执行。

那么在整个 过程中,最复杂的就是 方法了,下面我们来单独介绍它。

updateChildren

的逻辑比较复杂,直接读源码比较晦涩,我们可以通过一个具体的示例来分析它。

当我们点击 按钮去改变数据,最终会执行到 去更新 部分的列表数据,我们通过图的方式来描述一下它的更新过程:

第一步:

第二步:

第三步:

第四步:

第五步:

第六步:

总结

组件更新的过程核心就是新旧 vnode diff,对新旧节点相同以及不同的情况分别做不同的处理。新旧节点不同的更新流程是创建新节点->更新父占位符节点->删除旧节点;而新旧节点相同的更新流程是去获取它们的 children,根据不同情况做不同的更新逻辑。最复杂的情况是新旧节点相同且它们都存在子节点,那么会执行 逻辑,这块儿可以借助画图的方式配合理解。

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券