前端进阶之最长递增子序列算法和vue.js中的Diff算法

前端进阶之最长递增子序列算法和vue.js中的Diff算法

最长递增子序列

什么是子序列

子序列的概念派生自数组,通过删除(或不删除)数组中的元素而不改变其余元素的顺序,得到的数组就是原数组的子序列。
例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

[Leetcode] 300. 最长递增子序列

最长递增子序列问题是一个经典的算法问题,通过动态规划可以很好地理解和解决这个问题。但是在处理大数据集时,更好的方式是使用二分查找法将时间复杂度优化到 O(nlogn)

vue.js的Diff算法

在Vue.js中,Diff算法是虚拟DOM算法的核心部分,它负责比较新旧两个虚拟DOM树的差异,并计算出最小的更新操作来应用到真实的DOM上,从而达到渲染性能提高的最终目标。

DOM有哪几种操作:

  1. 挂载;
  2. 卸载;
  3. 修改(文本节点的变更);

移动DOM总比删除&创建DOM更高效,在获取最大移动次数的前提下,剩下的就是需要添加(新的VDom)和删除(旧的VDom)的dom元素。

  • 判断是否有节点需要移动,以及应该如何移动;
  • 找出那些需要被添加或移除的节点

Vue Diff算法的一些前提

  • 比较只会在同层级进行, 不会跨层级比较;
  • 在比较同层级的多个子节点时,Vue.js会从两端(头部和尾部)开始进行比较,这样可以快速处理那些仅在头部或尾部发生变化的情况;
  • 假如当前节点VNodeType或key不同,Vue.js会认为这是两个完全不同的节点,会进行替换操作。如果节点相同,Vue.js会检查节点的属性和子节点,并递归地应用Diff算法。

vue中用到的一些Diff方式

  1. 简单Diff;
  2. 双端Diff;
  3. 快速Diff;

简单Diff

遍历新旧两组子节点中数量较少的那一组,并逐个调用patch函数进行打补丁,然后比较新旧两组子节点的数量,如果新的一组子节点数量更多,说明有新子节点需要挂载;否则说明在旧的一组子节点中,有节点需要卸载。

另外,可以通过给节点增加属性key作为身份标识符,以此来确定新旧节点的对应关系,从而找出可复用的节点。

然后,拿新的一组子节点中的节点去旧的一组子节点中寻找可复用的节点。如果找到了,则记录该节点的位置索引。我们把这个位置索引称为最大索引。在整个更新过程中,如果一个节点的索引值小于最大索引,则说明该节点对应的真实 DOM 元素需要移动。

双端Diff

  1. 对于新旧两组子节点,首先分别对头部和尾部进行对比,找出未移动的节点。
  2. 在上一步完成后,在对比完成后的基础上,进行交叉对比,即旧头和新尾,旧尾和新头进行对比,进一步找出可复用的节点。
  3. 接下来,在剩余未对比的节点中,找出可复用的节点。先是创建一个Key -> Index 的哈希表,用来记录旧节点的索引顺序。然后通过遍历新的一组节点,根据key找出可复用的节点。
  4. 完成上述三步后,删除未复用的节点,创建新增的节点,并对复用的节点根据新的顺序进行移动操作。

双端Diff算法是Vue.js 2用于比较新旧两个子节点的方式。它的核心逻辑是在新旧两组子节点的四个端点之间分别进行比较,并试图找到可复用的节点。相比简单Diff算法,双端Diff算法的优势在于,对于同样的更新场景,执行的DOM移动操作次数更少。

快速Diff

这是vue3采用的Diff算法。

通过key确定当前节点是否可复用,假如key相等,则只针对当前节点下的子节点children进行diff。

预处理操作

「去除相同前置和后置元素」 ,此优化由 Neil Fraser 提出,可以比较容易实现而且带来带来比较明显的提升;

先处理掉相同的前置节点和后置节点,假如用字符串作为例子🌰去描述的话,应该是是这样的:

// 预处理之前的数据
let oldStr = "I'm OK"
let newStr = "I am not OK"
// 预处理完成后的数据
oldStr = "'m"
newStr = " am not"

原字符串中相同的前置部分的I 和 后置部分的 OK被处理掉,只保留内容不同的部分。然后再把旧的子字符串('m)删掉,新的子字符串( am not)添加进去即可。

但是,对你一定会说但是。

这种情况是比较理想的一种情况,假如没有任何相同的前置和后置节点,且存在乱序的可复用DOM节点,应该如何才能最大限度的减少DOM的操作次数呢?这时候就可以用到最长递增子序列算法了。

为什么最长递增子序列能保证DOM操作次数最少?

子序列的特点就是元素在原数组的中相对位置保持一致,即假如元素x在原数组中处于元素y的后面,那么在子序列中也一定会处在元素y的后面。
现在我们把数组元素换成DOM元素的话,子序列就能保证新旧DOM中的元素位置关系不会变。
最长能保证最多的DOM元素位置关系没有变更,从而确保需要DOM变动的次数最少。

PatchFlag —— 一个小插曲

Vue 3借助PatchFlag实现了靶向更新

在Vue 2中,每次更新都需要进行全量对比,而Vue 3通过引入静态标记来减少非动态内容的对比消耗。这种方法只对比带有标记的部分,从而提高了更新的效率。具体实现是在compile阶段将获取的PatchFlag信息存储到VNode上。当在进行Diff时,针对不同类型的PatchFlag,进行不同的处理处理,以达到降低Diff成本的目的。假如没有标记type信息,则按照传统流程进行full diff。

例如,如果一个节点只有class属性可能变化,那么在patch过程中只需要检查class属性,而不是进行全属性比较。

静态标记使用位运算符进行组合和检查。例如,可以通过|运算符来组合多个标记,使用&运算符来检查某个标记是否存在。

PatchFlag 有哪些类型

  • TEXT:动态文本节点
  • CLASS:动态class绑定
  • STYLE:动态style
  • PROPS:动态属性,不包括类名和样式
  • FULL_PROPS:动态key,当key变化时需要完整的diff算法比较
  • HYDRATE_EVENTS:带有事件监听器的节点
  • STABLE_FRAGMENT:子节点顺序不变的Fragment
  • KEYED_FRAGMENT:带有key属性的Fragment
  • UNKEYED_FRAGMENT:子节点没有key的Fragment
  • NEED_PATCH:只需要non-props修补的元素
  • DYNAMIC_SLOTS:动态的slot
  • DEV_ROOT_FRAGMENT:仅因为用户在模板根级别放置注释而创建的片段(开发时使用的标志)
  • HOISTED:已提升的静态vnode,更新时跳过整个子树
  • BAIL:指示diff算法退出优化模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/792859.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter仿Boss-4.短信验证码界面

效果 简述 在移动应用开发中,处理短信验证码是确保用户身份验证和安全性的重要步骤。本文将介绍如何使用Flutter构建一个短信验证码界面,让用户输入通过短信发送到他们手机的四位验证码。 依赖项 在这个项目中,我们将使用以下依赖项&#…

vue快速入门(六)v-else和v-else-if

注释很详细&#xff0c;直接上代码 上一篇 新增内容 v-else-if用法v-else用法 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-s…

枚举类练习

练习一 案例&#xff1a;使用枚举类实现单例模式 package chapter08_oop3_teacher.src.com.atguigu10._enum.exer1;/*** ClassName: BankTest1* Description:** Author 尚硅谷-宋红康* Create 15:05* Version 1.0*/ public class BankTest1 {public static void main(String[]…

Excel、PowerQuery 和 ChatGPT 终极手册(上)

原文&#xff1a;Ultimate ChatGPT Handbook for Enterprises 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 序言 在不断发展的数据管理和分析领域中&#xff0c;掌握 Excel 的查找功能不仅是一种技能&#xff0c;更是高效数据处理的基石。《使用 Power Query 和 Ch…

论文阅读:Walk These Ways: 通过行为多样性调整机器人控制以实现泛化

Walk These Ways: 通过行为多样性调整机器人控制以实现泛化 摘要&#xff1a; 通过学习得到的运动策略可以迅速适应与训练期间经历的类似环境&#xff0c;但在面对分布外测试环境失败时缺乏快速调整的机制。这就需要一个缓慢且迭代的奖励和环境重新设计周期来在新任务上达成良…

Django模板层——三种自定义模板simple_tag、inclusion_tag、filter的用法

目录 1. 前言 2. 前置操作 3. simple_tag 3.1 注意点 4. inclusion_tag 5. filter 6. 结尾 1. 前言 在前后端不分离的模式中&#xff0c;Django的模板语法尤为重要&#xff0c;我们可以动态传入变量&#xff0c;并在前端HTML中进行展示。在变量展示时&#xff0c;会有一…

JavaWeb中的Servlet是什么?怎么使用?

文章目录 一、什么是Servlet二、Servlet的基本内容1、Servlet的作用2、Servlet接口3、Servlet接口实现类4、Servlet接口实现类开发步骤5、Servlet对象生命周期6、HttpServletResquest接口7、HttpServletResponse接口8、请求对象和响应对象流程图9、请求对象和响应对象生命周期1…

vulhub中Apache Solr 远程命令执行漏洞复现(CVE-2019-0193)

Apache Solr 是一个开源的搜索服务器。Solr 使用 Java 语言开发&#xff0c;主要基于 HTTP 和 Apache Lucene 实现。此次漏洞出现在Apache Solr的DataImportHandler&#xff0c;该模块是一个可选但常用的模块&#xff0c;用于从数据库和其他源中提取数据。它具有一个功能&#…

vue给input密码框设置眼睛睁开闭合对于密码显示与隐藏

<template><div class"login-container"><el-inputv-model"pwd":type"type"class"pwd-input"placeholder"请输入密码"><islot"suffix"class"icon-style":class"elIcon"…

三子棋(C游戏)

文章目录 三子棋的描述思路关键代码运行代码 三子棋的描述 三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战&#xff0c;双方依次在9宫格棋盘上摆放棋子&#xff0c;率先将自己的三个棋子走成一条线就视为胜利&#xff0c;…

机器学习之常用的回归预测模型

本文全面整理了各种回归预测模型&#xff0c;旨在帮助读者更好地学习回归预测模型。 转载自&#xff1a;https://mp.weixin.qq.com/s/7m2waIASOEg90NONgRpQFQ 一.线性模型 线性回归是一种线性模型&#xff0c;通过特征的线性组合来预测连续值标签。线性回归通过拟合系数 &…

实现 select 中嵌套 tree 外加搜索

实现 select 中嵌套 tree 外加搜索 参考地址实现地址 代码 <el-form-item label"考核人员" prop"userIdArr" v-if"title 发起考核"><el-popover v-model"popoverVisible" placement"bottom" trigger"cli…

论文笔记:Teaching Large Language Models to Self-Debug

ICLR 2024 REVIEWER打分 6666 1 论文介绍 论文提出了一种名为 Self-Debugging 的方法&#xff0c;通过执行生成的代码并基于代码和执行结果生成反馈信息&#xff0c;来引导模型进行调试不同于需要额外训练/微调模型的方法&#xff0c;Self-Debugging 通过代码解释来指导模型识…

Windows Server 2008 (限制用户登录时间、为客户机设置统一的桌面背景、管理用户统一安装软件、隐藏用户C盘)

一、限制用户登陆时间 Server&#xff1a; Client&#xff1a; Server&#xff1a; 将新建的用户移动到group1下 限制用户登陆时间 二、为客户机设置统一的桌面背景 Server&#xff1a; 将jpg图片放到abc文件夹中&#xff0c;并且设置文件夹共享模式 三、管理用户统一安装软件…

DFS:深搜+回溯+剪枝解决矩阵搜索问题

创作不易&#xff0c;感谢三连&#xff01;&#xff01; 一、N皇后 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<vector<string>> ret;vector<string> path;bool checkcol[9];bool checkdig1[18];bool checkdig2[18];int n…

WordPress主题–Applay v3.7.1 开心版下载

Applay是一款功能强大的多用途WordPress主题&#xff0c;专为应用展示、应用商店、商业和购物等Woocommerce网站而设计。它配备了拖曳式页面编辑功能&#xff0c;类似于Elementor&#xff0c;让您能够轻松构建和定制您的网站。无论您有什么需求&#xff0c;都可以尝试下这个主题…

pandas中apply() 函数的应用

apply() 函数是 Pandas 中用于对 DataFrame 或 Series 中的数据进行自定义函数处理的函数。它可以将一个函数应用到 DataFrame 或 Series 的每一行或每一列&#xff0c;从而实现对数据的批量处理。 对于 Series 和 DataFrame&#xff0c;apply() 函数的基本语法如下&#xff1…

Flutter 画笔(Paint)、绘制直线(drawLine)

override bool shouldRepaint(CustomPainter oldDelegate) > true; } class MyPainter extends CustomPainter { override void paint(Canvas canvas, Size size) { //画背景 var paint Paint() …isAntiAlias false …strokeWidth30.0 …color Colors.red; c…

什么是Android ABI?

2024年4月4日&#xff0c;周四晚上 在Android开发中&#xff0c;ABI&#xff08;Application Binary Interface&#xff09;指的是应用程序二进制接口&#xff0c;它定义了应用程序与底层操作系统及硬件之间的接口规范。ABI包括了函数调用约定、数据类型、寄存器使用规则等内容…

金融贷款批准预测项目

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 在金融服务行业&#xff0c;贷款审批是一项关键任务&#xff0c;它不仅关系到资金的安全&#xff0c;还直接影响到金融机构的运营效率和风险管理…