后端程序员入门react笔记——react的diff算法(三)

diffing算法

虚拟dom

我们知道,react里面操作的都是虚拟dom,最后经过render渲染为真正的dom,那么为什么要提出虚拟dom这个概念呢?其实就是将逻辑和视图区分开,react的虚拟dom,就相当于mvc的c,将数据逻辑和真正的dom区分开,我们知道,对于前端来说dom操作是非常昂贵的,性能消耗最大的就是dom操作。而virtual dom减少了对dom的操作,,不仅避免了资源浪费,而且页面的构建也得到了很大的提升。

为什么要diff

前面我们说了,应避免过多的操作dom,那么diff就是解决了这种问题。我们知道,react在状态发生变化的时候,会批量更新dom,生成新的UI,但是难道state的某一个值发生变化就要导致整个dom重新渲染吗?这明显是不科学的,为了解决这种问题,react提出了diff算法,通过对比新旧的两个虚拟dom树来检测那些dom是真的需要重新如安然,哪些dom是没有变化的。

diff算法

传统的diff算法是通过循环递归的方式对节点一次进行对比,需要O(n ^3)的时间复杂度。为什么?我们从最简单的说,把一棵树转换为另外一棵树,其实就是把一颗n个节点的树挨个儿去另一棵n个节点的树中查找,整个过程是n*n,那么如果发现有不同的地方,我们就需要需改,对一棵树的增删改的算法复杂度是n,那么整个过程就是n*n*n
在这里插入图片描述
react将这种对比策略做了一个优化,将复杂度降到了O(n),那么react是怎么实现的呢?react的diff会预设三个限制

  • 只进行同层级比较
  • 新旧节点的type不同,直接删除旧节点,创建新节点,比如组件不同,元素的类型不同,原来是ul,里面是li,后来改成了div+p,这个时候就会删除旧dom,创建新的dom.
  • 通过key来复用节点

在上面三个限制的基础上,对tree,conponent,element的处理方式又做了优化

  • dom节点不一致直接删除旧节点,创建新节点
  • 组件类型不一致直接删除组件下所有节点,创建新节点
  • 同一层的dom元素,以每个元素对应的key为标识,提供三种操作方式,删除新建和移动
    在这里插入图片描述

diff的最小颗粒度

diff的最小颗粒度是标签,我们举例看一下

class Hello extends React.Component {state={time:new Date()}componentDidMount(){this.timer=setInterval(()=>{this.setState({time:new Date()})},5000)}render() {console.log("i am render")return (<ul><li>备注:<input type="text"/></li><li><span>{this.state.time.toTimeString()}</span></li></ul>)}
}

我们看到,每隔5秒,span标签就会从新刷新一次,而其他元素没有变化
在这里插入图片描述

key

前面我们说了,同一层级的元素如果发生了变化,可以删除 插入和移动,前提是必须有key作为标识,如果没有key,比如下面代码

class Hello extends React.Component {state = {heros: [{id: 1,name: "张三"},{id: 2,name: "李四"}]}render() {console.log("i am render")return (<ul>{this.state.heros.map((hero,index)=>{return <li>{hero.name}</li>})}</ul>)}
}

这个时候浏览器提示了一个warm ,意思是每一个child都应该有唯一key。
在这里插入图片描述
那么这个key应该怎么选取呢

  • 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
  • 如果确定只是简单的展示数据,用index也是可以的。 但是不推荐。
    为什么不推荐index作为key,官方文档说,如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。

我们来举个例子对比一下,再分析问题所在。这段代码里,我点击添加按钮的时候,改变了原来数组对象的顺序,在数组的前头添加了一个对象,我们点击看一下效果

class Hello extends React.Component {state = {heros: [{id: 1,name: "张三"},{id: 2,name: "李四"}]}addHero=()=>{this.setState({heros: [{id: 3,name: "王五"},...this.state.heros]})}render() {console.log("i am render")return (<ul><button onClick={this.addHero}>点击添加王五</button><h1>index as key</h1>{this.state.heros.map((hero,index)=>{return <li key={index}>{hero.name}<input type="text" /></li>})}<h1>age as key</h1>{this.state.heros.map((hero,index)=>{return <li key={hero.id}>{hero.name}<input type="text" /></li>})}</ul>)}
}

在这里插入图片描述
我们发现了什么,以index做为key,input框并没有跟着往下移动,id作为key的往下移动了,我们发现问题了,那么为什么index作为key,input框不往下移动呢?就是因为数据的顺序发生变化了,王五被塞进了数组对象的头部,但是diff的时候,由于元素的key是index,还是从0开始的,并没有发生变化,所以input框并不会移动。

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

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

相关文章

Windows下载MobaXterm软件访问远程服务器的方法

本文介绍在Windows电脑中&#xff0c;下载、配置MobaXterm软件&#xff0c;从而连接、操作远程服务器的方法。 因为是在Windows操作系统的电脑中连接服务器&#xff0c;所以建议使用MobaXterm、PuTTY等可视化的远程计算机管理软件&#xff0c;来实现对服务器的连接与后续相关操…

如何用代理IP防止被泄露真实IP地址?

随着互联网的普及&#xff0c;我们的网络行为越来越离不开IP地址。然而&#xff0c;由于一些不法分子利用IP地址进行网络攻击、窃取个人信息等行为&#xff0c;保护我们的真实IP地址变得尤为重要。代理IP地址是一种隐藏真实IP地址的方法&#xff0c;通过使用代理服务器来中转网…

HTML+CSS+JS:花瓣登录组件

效果演示 实现了一个具有动态花朵背景和简洁登录框的登录页面效果。 Code <section><img src"./img/background.jpeg" class"background"><div class"login"><h2>Sign In</h2><div class"inputBox"…

并发编程入门指南

文章目录 并发编程进程和线程的区别并发和并行的区别创建线程的方式线程之间的状态&#xff0c;状态之间的转换新建三个线程&#xff0c;如何保证按顺序执行wait方法和sleep的区别如何停止一个正在运行的线程synchronized关键字底层原理Monitor属于重量级锁&#xff0c;了解过锁…

【Vue3】toRefs和toRef在reactive中的一些应用

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

Mybatis速成(二)

文章目录 1. Mybatis基础操作1.1 需求1.2 准备1.3 删除1.3.1 功能实现1.3.2 日志输入1.3.3 预编译SQL1.3.3.1 介绍1.3.3.2 SQL注入1.3.3.3 参数占位符 1.4 新增1.4.1 基本新增1.4.2 主键返回 1.5 更新1.6 查询1.6.1 根据ID查询1.6.2 数据封装1.6.3 条件查询1.6.4 参数名说明 2.…

如何选择最适合的图纸加密软件?用户体验及性价比

安秉网盾图纸加密软件是一款功能强大的图纸加密工具&#xff0c;具有以下特点和优势&#xff1a; 全盘加密&#xff1a;安秉网盾采用先进的加密算法&#xff0c;能对文件、文件夹、磁盘等数据进行全面加密&#xff0c;确保数据在存储和传输过程中的安全性。 监控与审计&#…

Android进阶(二十九) 走近 IntentFilter

文章目录 一、什么是IntentFilter &#xff1f;二、IntentFilter 如何过滤隐式意图&#xff1f;2.1 动作测试2.2 类别测试2.3 数据测试 一、什么是IntentFilter &#xff1f; 如果一个 Intent 请求在一片数据上执行一个动作&#xff0c; Android 如何知道哪个应用程序&#xf…

【Linux系统化学习】深入理解匿名管道(pipe)和命名管道(fifo)

目录 进程间通信 进程间通信目的 进程间通信的方式 管道 System V IPC&#xff08;本地通信&#xff09; POSIX IPC&#xff08;网络通信&#xff09; 管道 什么是管道 匿名管道 匿名管道的创建 匿名管道的使用 匿名管道的四种情况 匿名管道的五种特性 命名管道 …

机器视觉缺陷检测目前面临着哪些挑战?

机器视觉缺陷检测是工业自动化领域的一项关键技术&#xff0c;能够大幅提高生产效率和产品质量。然而&#xff0c;在实际应用中&#xff0c;机器视觉缺陷检测面临着诸多挑战。以下是对这些挑战的详细分析&#xff1a; 1、数据量大、处理速度慢&#xff1a;在实际生产线中&#…

JAMA Neurology(IF: 29):神经源性细胞外囊泡α-Synuclein作为患帕金森病风险个体的血清生物标志物

帕金森病 (Parkinson disease, PD) 是最常见的运动障碍疾病&#xff0c;其特点是前驱期较长&#xff0c;在出现典型运动症状的临床表型前几年就开始了。许多非运动症状可能在前驱期表现出来&#xff0c;如快速动眼睡眠行为障碍 (rapid eye movement sleep behavior disorder, R…

一分钟学会MobaXterm当Linux客户端使用

一、介绍 MobaXterm是一款功能强大的远程计算机管理工具&#xff0c;它集成了各种网络工具和远程连接协议&#xff0c;可以帮助用户在Windows系统上轻松管理远程计算机。MobaXterm支持SSH、Telnet、RDP、VNC等多种远程连接协议&#xff0c;同时还集成了X11服务器&#xff0c;可…