• 事件缓存:将事件缓存,可以理解为变成静态的了
  • 添加静态标记:Vue2 是全量 Diff,Vue3 是静态标记 + 非全量 Diff
  • 静态提升:创建静态节点时保存,后续直接复用
  • 使用最长递增子序列优化了对比流程:Vue2 里在 updateChildren() 函数里对比变更,在 Vue3 里这一块的逻辑主要在 patchKeyedChildren() 函数里,具体看下面

事件缓存

<button @click="handleClick">按钮</button>编译后结果
export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createElementBlock("button", {onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.handleClick && _ctx.handleClick(...args)))}, "按钮"))
}

onClick 会先读取缓存,如果缓存没有的话,就把传入的事件存到缓存里,都可以理解为变成静态节点了

静态标记

export const enum PatchFlags {TEXT = 1 ,  // 动态文本节点CLASS = 1 << 1,  // 2   动态classSTYLE = 1 << 2,  // 4   动态stylePROPS = 1 << 3,  // 8   除去class/style以外的动态属性FULL_PROPS = 1 << 4,       // 16  有动态key属性的节点,当key改变时,需进行完整的diff比较HYDRATE_EVENTS = 1 << 5,   // 32  有监听事件的节点STABLE_FRAGMENT = 1 << 6,  // 64  一个不会改变子节点顺序的fragment (一个组件内多个根元素就会用fragment包裹)KEYED_FRAGMENT = 1 << 7,   // 128 带有key属性的fragment或部分子节点有keyUNKEYEN_FRAGMENT = 1 << 8, // 256  子节点没有key的fragmentNEED_PATCH = 1 << 9,       // 512  一个节点只会进行非props比较DYNAMIC_SLOTS = 1 << 10,   // 1024   动态slotHOISTED = -1,  // 静态节点 BAIL = -2      // 表示 Diff 过程中不需要优化
}
<div id="app"><div>jeff</div><p>{{ age }}</p>
</div>编译结果为:
const _hoisted_1 = { id: "app" }
const _hoisted_2 = /*#__PURE__*/_createElementVNode("div", null, "jeff", -1 /* HOISTED */)export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createElementBlock("div", _hoisted_1, [_hoisted_2,_createElementVNode("p", null, _toDisplayString(_ctx.age), 1 /* TEXT */)]))
}

看到上面编译结果中的 -1 和 1 了吗,这就是静态标记,这是在 Vue2 中没有的,patch 过程中就会判断这个标记来 Diff 优化流程,跳过一些静态节点对比

静态提升
在 Vue2 里每当触发更新的时候,不管元素是否参与更新,每次都会全部重新创建
而在 Vue3 中会把这个不参与更新的元素保存起来,只创建一次,之后在每次渲染的时候不停地复用,比如上面例子中的静态的创建一次保存起来

const _hoisted_1 = { id: "app" }
const _hoisted_2 = /*#__PURE__*/_createElementVNode("div", null, "jeff", -1 /* HOISTED */)

然后每次更新 age 的时候,就只创建这个动态的内容,复用上面保存的静态内容

export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createElementBlock("div", _hoisted_1, [_hoisted_2,_createElementVNode("p", null, _toDisplayString(_ctx.age), 1 /* TEXT */)]))
}

patchKeyedChildren
在 Vue2 里 updateChildren 会进行

  • 头和头比
  • 尾和尾比
  • 头和尾比
  • 尾和头比
  • 都没有命中的对比

在 Vue3 里 patchKeyedChildren 为

  • 头和头比
  • 尾和尾比
  • 基于最长递增子序列进行移动/添加/删除

看个例子,比如

  • 老的 children:[ a, b, c, d, e, f, g ]
  • 新的 children:[ a, b, f, c, d, e, h, g ]

1、先进行头和头比,发现不同就结束循环,得到 [ a, b ]
2、再进行尾和尾比,发现不同就结束循环,得到 [ g ]
3、再保存没有比较过的节点 [ f, c, d, e, h ],并通过 newIndexToOldIndexMap 拿到在数组里对应的下标,生成数组 [ 5, 2, 3, 4, -1 ],-1 是老数组里没有的就说明是新增
4、然后再拿取出数组里的最长递增子序列,也就是 [ 2, 3, 4 ] 对应的节点 [ c, d, e ]
5、然后只需要把其他剩余的节点,基于 [ c, d, e ] 的位置进行移动/新增/删除就可以了

vue3 diff算法优化相关推荐

  1. vue3 - diff算法之快速diff算法

    快速Diff算法 预处理 前面讲到简单Diff算法和双端Diff算法,它们使用不一样的对比规则对虚拟节点的 type(元素名)和 虚拟节点的key(唯一标识)来区分是否有可以复用的旧节点.快速Diff ...

  2. 做diff_Vue3.0时代你必须了解的:diff算法原理和优化

    关注前端公众号 [前端每日一博] 前言 面试官: 你知道 Vue3.0 Object.difineProperty和vue3.0的proxy的区别吗? 你知道 Vue3.0 diff算法原理和它有什么 ...

  3. vue-vue2和vue3的diff算法

    核心要点 数据变化时,vue如何更新节点 虚拟DOM 和 真实DOM 的区别 vue2 diff 算法 vue3 diff 算法 一. 数据变化时,vue如何更新节点 首先渲染真实DOM的开销是很大, ...

  4. 【手写 Vue2.x 源码】第二十八篇 - diff 算法-问题分析与 patch 优化

    一,前言 首先,对 6 月的更文内容做一下简单回顾: Vue2.x 源码环境的搭建 Vue2.x 初始化流程介绍 对象的单层.深层劫持 数组的单层.深层劫持 数据代理的实现 对象.数组数据变化的观测 ...

  5. Vue中的Diff算法 patch函数-简单Diff算法-双端Diff算法-快速Diff算法-当数据发生改变,视图如何更新?

    文章目录 Vue中的Diff算法 概述 前置知识 patch方法 简单Diff算法 总结 双端Diff算法 --vue2 快速Diff算法 --vue3 vue2和vue3 Diff算法的区别 当数据 ...

  6. diff算法_深入剖析Vue源码 - 来,跟我一起实现diff算法!__Vue.js

    这一节,依然是深入剖析Vue源码系列,上几节内容介绍了Virtual DOM是Vue在渲染机制上做的优化,而渲染的核心在于数据变化时,如何高效的更新节点,这就是diff算法.由于源码中关于diff算法 ...

  7. 深入浅出虚拟 DOM 和 Diff 算法,及 Vue2 与 Vue3 中的区别

    因为 Diff 算法,计算的就是虚拟 DOM 的差异,所以先铺垫一点点虚拟 DOM,了解一下其结构,再来一层层揭开 Diff 算法的面纱,深入浅出,助你彻底弄懂 Diff 算法原理 认识虚拟 DOM ...

  8. vue2与vue3的diff算法区别

    Vue2和Vue3的diff算法有一些区别: Vue2使用双向指针来进行虚拟DOM的比较,而Vue3则使用了单向链表的方式. 在计算key值不同时,Vue2会采用首尾两端比较的方法,而Vue3则采用了 ...

  9. 学习Vue3 第五章(Vue核心虚拟Dom和 diff 算法)

    为什么要学习源码 1.可以提升自己学习更优秀的API设计和代码逻辑 2.面试的时候也会经常问源码相关的东西 3.更快的掌握vue和遇到问题可以定位 介绍虚拟DOM 虚拟DOM就是通过JS来生成一个AS ...

最新文章

  1. 侠客X官方网站成立,第一个内测版本即将放出,敬请期待.
  2. 来客推商城V3多用户uni-app商城源码如何搭建?盈利模式怎么样的?
  3. 最亲密接触DhtmlJScript开发细节
  4. Atitit 热烈庆祝读经器项目圆满完成
  5. 技术干货 | 闲鱼:一个优秀的 Push 平台,需要经历怎样的前世今生
  6. python学习笔记9-函数1
  7. html如何取消盒子间的间隔,使用flexbox时,多行子元素之间的间距如何控制?
  8. SWT folder ‘..\framework\x86_64‘ does not exist. Please set ANDROID_SWT to point to the folder conta
  9. Solr7.3 Cloud On HDFS搭建
  10. ie浏览器中 textarea 不能自动换行
  11. Mac vscode花屏问题解决
  12. 黑马品优购项目的总结-首页
  13. 03惯性导航系统误差分析
  14. 会员数据化运营(一)
  15. Stable Diffusion半秒出图;VLIW的前世今生;YOLOv5全面解析教程 | AI系统前沿动态
  16. 2022-2028年中国冷冻草莓加工行业市场竞争态势及发展趋向分析报告
  17. 体验服官网和平精英维护服务器,和平精英体验服怎么注册?和平精英体验服注册流程...
  18. java doc转换docx_使用Java将DOC文件转换为DOCX
  19. 猜数游戏(人机交互)
  20. DingTalk「开发者说」|钉钉小程序开发实践

热门文章

  1. 如何判断树莓派GPIO引脚是否损坏
  2. 通过access口加vlan标签吗_一文看懂VLAN的作用
  3. python有多少关键字_Python中有几个关键字
  4. 【Delphi】微信支付控件(一)(半小时让您系统拥有支付功能)源代码、帮助文件、演示程序
  5. 数学空间 Space
  6. uploadifive 下载_Win 平台最好的下载工具
  7. c语言队列程序怎么写,[原创]非常漂亮的队列演示程序(C语言版)
  8. 计算直柱体的面积和体积
  9. 医学影像坐标系问题(世界坐标系、解剖坐标系和图像坐标系)
  10. javascript的参数_如何使用JavaScript制作参数家具