什么是“最长递增子序列”算法?深度解析 Vue3 如何计算节点移动的最优路径

千丽同学_6699

千丽同学_6699

2026-05-07

124人浏览

原创

vue3用最长递增子序列(lis)优化dom diff,通过构建新旧节点索引映射数组并求其lis,确定最多可复用的不动节点,仅移动其余节点,将dom操作降至最少,时间复杂度为o(n log n)。

什么是“最长递增子序列”算法?深度解析 vue3 如何计算节点移动的最优路径

最长递增子序列(Longest Increasing Subsequence,简称 LIS)不是指连续的一段,而是从原序列中**按原始顺序挑出若干元素**,使其严格递增,且长度尽可能长。它不关心元素是否相邻,只关注“顺序”和“大小关系”。Vue 3 把这个数学概念巧妙地用在 DOM 节点移动优化上:找出哪些节点可以不动,只移动其余节点,从而把真实 DOM 操作降到最少。

为什么 LIS 能减少 DOM 移动?

在列表更新时,如果新旧节点顺序发生乱序(比如旧顺序是 [A, B, C, D],新顺序是 [A, D, B, C]),直接逐个比对再移动容易重复操作。Vue 3 的思路是:先构建一个映射数组 newIndexToOldIndexMap,记录新列表中每个位置对应旧列表的索引(若无对应则为 0)。对这个映射数组求 LIS,就等于找出了**最多可以保留原位置、无需移动的节点集合**。

例如:
旧节点顺序(带索引):A(0), B(1), C(2), D(3)
新节点顺序:A, D, B, C → 对应旧索引数组为 [0, 3, 1, 2]
该数组的 LIS 是 [0, 1, 2](对应 A→B→C),说明这三个节点在新列表中的相对顺序与旧列表一致,只需把 D 插入到 A 后面即可,其他节点不动。

Vue 3 实际怎么算 LIS?用的是贪心 + 二分查找

Vue 3 没有用 O(n²) 的动态规划,而是采用时间复杂度仅 O(n log n) 的贪心策略,核心逻辑是维护一个“结果索引数组”,它不直接存数值,而是存原数组中满足条件的**下标**:

  • 遍历 newIndexToOldIndexMap 中每个值(即旧索引)
  • 跳过值为 0 的项(代表全新节点,不参与移动判断)
  • 若当前值大于结果数组末尾对应位置的旧索引,就追加进去
  • 否则用二分查找找到结果数组中第一个 ≥ 当前值的位置,并替换它
  • 最后通过前驱数组反向追溯,还原出真正的 LIS 下标序列

这个过程不追求中间结果“看起来像原序列”,只要保证最终长度准确、且能支撑后续节点复用逻辑即可——Vue 关注的是“最少移动次数”,不是“展示最漂亮子序列”。

vue-composition-api-best-practices
vue-composition-api-best-practices

Vue 3 组合式 API 与

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
uni-app快速上手
uni-app快速上手

共0课时 | 0人学习

Vue 教程
Vue 教程

共42课时 | 17.2万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 2.5万人学习