• React之DOM的diff算法


    DOM的diff算法

    React展示前端首先将DOM转换为虚拟DOM,然后再生成页面上的真实DOM,因此当DOM更新时,React会先更新虚拟DOM,然后将新的虚拟DOM与旧的进行对比,如果遇到相同的,页面上对应的DOM就不需要变动,如果遇到不相同的,那么就更新对应页面上的DOM。

    这样的好处就是当一个页面内容很多,但是每次只需要更新一点点内容时,React就会有比较好的性能。

    react中的key有什么作用?

    虚拟DOM中key的作用:

    1) 简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。、
    2) 详细的说:当状态中的数据发生变化时,react会根据新数据生成新的虚拟DOM,随后React进行新虚拟DOM与旧虚拟DOM的diff比较比较规则如下:
    a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
    (1). 若虚拟DOM中的内容没变,直接使用之前的真实DOM
    (2). 若虚拟DOM中的内容变了,则生成真实DOM,随后替换掉页面中之前的真实DOM
    b. 旧虚拟DOM中未找到与新虚拟DOM相同的key,根据数据创建新的真实DOM,随后渲染到网页。

    为什么遍历列表时,key最好不要用index?

    用index作为key可能会引发的问题:

    1)若对数据进行:逆序添加、逆序删除等破环顺序操作,会产生没有必要的真实DOM更新 界面效果没问题,单效率低
    2) 如果结构中还包含输入类的DOM,会产生错误DOM更新界面有问题
    3) 注意!如果不存在对数据逆序添加、逆序删除等破环顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

    开发中如何选择key?

    1.最好使用每条数据唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
    2.如果确定只是简单的展示数据,用index也是可以的

    实例

    用个实例来感受一下。

    假设这里是逆序添加元素,就会导致一些问题:

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        <div id="test">div>
    
        <script src="../js/react.development.js">script>
        <script src="../js/react-dom.development.js">script>
        <script src="../js/babel.min.js">script>
        <script src="../js/prop-types.js">script>
        <script type="text/babel">
    
            class Person extends React.Component{
                state = {
                    persons:[
                        {id:1, name:"小张", age:18},
                        {id:2, name:"小李", age:19},
                    ]
                }
                add = () => {
                    const {persons} = this.state;
                    const p = {id:persons.length+1, name:"小王", age:20}
                    this.setState({persons:[p,...persons]})
                }
                render(){
                    return (
                        <div>
                        <h2>展示人员信息</h2>
                        <button onClick={this.add}>添加一个小王</button>
                        <h3>使用index(索引值)作为key</h3>
                        <ul>{
                        this.state.persons.map((personObj, index) => {
                            return <li key={index}>{personObj.name}----{personObj.age}<input type="text"/></li> 
                        })
                    }
                        </ul>
                        <hr/>
                        <hr/>
                        <h3>使用id(数据唯一标识)作为key</h3>
                        <ul>{
                        this.state.persons.map((personObj, index) => {
                            return <li key={personObj.id}>{personObj.name}----{personObj.age}<input type="text"/></li> 
                        })
                    }
                        </ul>
                        </div>)
                }
            }
            ReactDOM.render(<Person/>, document.getElementById("test"))
        script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    运行后
    在这里插入图片描述
    页面文本框输入对应的信息,然后点击按钮

    在这里插入图片描述
    发现逆序添加元素时
    在这里插入图片描述

    用index会导致错位,因为
    index原本是 小张0,小李1,现在逆序添加小王,那么现在小王为0,小张1,小李2,导致DOM得重新生成,而输入框的内容并未改变,则保留,就会导致这样的错误。

    但是如果顺序添加元素,这个实例其实也没什么问题:

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        <div id="test">div>
    
        <script src="../js/react.development.js">script>
        <script src="../js/react-dom.development.js">script>
        <script src="../js/babel.min.js">script>
        <script src="../js/prop-types.js">script>
        <script type="text/babel">
    
            class Person extends React.Component{
                state = {
                    persons:[
                        {id:1, name:"小张", age:18},
                        {id:2, name:"小李", age:19},
                    ]
                }
                add = () => {
                    const {persons} = this.state;
                    const p = {id:persons.length+1, name:"小王", age:20}
                    this.setState({persons:[...persons,p]})
                }
                render(){
                    return (
                        <div>
                        <h2>展示人员信息</h2>
                        <button onClick={this.add}>添加一个小王</button>
                        <h3>使用index(索引值)作为key</h3>
                        <ul>{
                        this.state.persons.map((personObj, index) => {
                            return <li key={index}>{personObj.name}----{personObj.age}<input type="text"/></li> 
                        })
                    }
                        </ul>
                        <hr/>
                        <hr/>
                        <h3>使用id(数据唯一标识)作为key</h3>
                        <ul>{
                        this.state.persons.map((personObj, index) => {
                            return <li key={personObj.id}>{personObj.name}----{personObj.age}<input type="text"/></li> 
                        })
                    }
                        </ul>
                        </div>)
                }
            }
            ReactDOM.render(<Person/>, document.getElementById("test"))
        script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    运行结果:
    在这里插入图片描述

    总结

    所有还是需要将key设置为唯一标识,不能简单用index,因为可能到时候会出现bug。

  • 相关阅读:
    红外小目标:DNANet网络结构与模型搭建
    「随笔」前端面试 | 2022年前端面试基础必备
    全媒体时代,企业新闻通稿应该怎么写更具传播性
    3.1 Android eBPF代码仓解读
    阿里开源组件Nacos实战操作之安装部署完整版
    『Vscode 自定义折叠代码』
    css中的hover用法示例(可以在vue中制作鼠标悬停显示摸个按钮的效果)
    自然语言处理从零到入门 Encoder-Decoder 与 Seq2Seq
    在线客服功能介绍-了解常见在线客服系统的功能点
    AI学习指南数学工具篇-PCA的数学原理
  • 原文地址:https://blog.csdn.net/qq_52785473/article/details/126439384