• React18 渲染列表与添加key值


    引用原作者链接:渲染列表

    一、列表渲染

    现在,有这样一组数据,需要在页面中呈现:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    
    • 1

    如果想直接显示,可以直接将数组插入到JSX中,JSX会自动对数组展开并显示。但这样一来数据知识直接显示,不会添加任何的结构。如果希望将数组中的元素放到一个无序列表中显示,就需要对列表做一些处理了。

    <ul>
        <li>孙悟空li>
        <li>猪八戒li>
        <li>沙和尚li>
    ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可以使用for循环对其进行处理:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    const items = [];for(let i=0; i<students.length; i++){
        items.push(<li>{stus[i]}</li>);
    }const ele = <ul>{items}</ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上边操作的本质其实就是根据一个旧数组students生成了一个新数组items:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    const items = [
        <li>孙悟空</li>,
        <li>猪八戒</li>,
        <li>沙和尚</li>,
    ];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这个操作我们也可以通过map()方法来完成:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    const items = students.map(item => <li>{item}</li>);
    const ele = <ul>{items}</ul>
    
    • 1
    • 2
    • 3

    map()本身就是一个函数,所以我们完全可以直接将函数调用写在JSX中间:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    const ele = <ul>{students.map(item => <li>{item}</li>)}</ul>
    
    • 1
    • 2

    很显然使用map()比使用for循环要优雅很多,所以这也是我们在React中的常用方式。

    二、警告

    输出一个列表时,无论我们使用的for循环还是map()方法,当你打开控制台时你一定会看到一行红色的内容,它大概内容是:Warning: Each child in a list should have a unique “key” prop.

    Warning表示一个警告,警告表示它并不是一个特别严重的错误,但你最好把它处理了,所以当你在React项目中看到这个玩意的时候一定一定要想办法去除掉它。

    为什么会报出这个警告呢?事情要往前回溯一下,我们已经知道React是通过虚拟DOM来操作元素的,而React为了提升操作的性能,在DOM发生变化时只会去修改那些发生了变化的元素,这样就大大的减少了DOM操作从而提升了页面渲染的速度。

    React怎么知道哪些元素发生变化呢?其实也不难,React每次渲染都会生成一个由React元素构成的树(当然这棵树也对应着一课DOM元素构成的树,但是这里不太重要),React每次重新渲染都会生成一个新的React元素树,在页面刷新前,React会通过内部的diff算法对两个树中的React元素进行比较,并且找到那些发生变化的元素,并将他们的变化在真实的DOM元素上体现出来。

    这个算法听上去很神奇,其实很简单就是按照顺序比较两个元素,第一个和第一个比,第二个和第二个比,没有变化就放过,有变化就记录。

    扯了这么一长串,和上边的警告有什么关系吗?上边的例子中,我们把一个数组直接在JSX中呈现了出来。当我们第一次渲染时,列表可能是这样的:

    <ul>
        <li>孙悟空</li>
        <li>猪八戒</li>
        <li>沙和尚</li>
    </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    假使数组发生了变化(这里还没讲怎么变,想象一下吧!),页面需要重新渲染,变成了这样:

    <ul>
        <li>孙悟空</li>
        <li>猪八戒</li>
        <li>沙和尚</li>
        <li>唐僧</li>
    </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这里我们在列表的最后增加了一个唐僧,那么前边的元素顺序是不变的,孙悟空第一个,猪八戒第二,沙和尚第三。所以这里在应用修改时只会修改最后一个li,对前边的三个不会有任何影响!性能非常棒!

    但是,加入唐僧不想在最后,它想去第一个位置,像这样:

    <ul>
        <li>唐僧</li>
        <li>孙悟空</li>
        <li>猪八戒</li>
        <li>沙和尚</li>
    </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这时问题就来了,唐僧第一,孙悟空第二…换句话说,所有元素的顺序都变了,那么React在比较元素不同时,它并不能知道孙悟空从第一变到了第二个,它会任务是唐僧替换了孙悟空,孙悟空替换了猪八戒,猪八戒替换了沙和尚,然后又增加了一个沙和尚,导致页面渲染是四个li都被重新渲染了!如果列表里有100个元素,那么就是100个都得重新渲染,性能不好!

    那么这种情况,我们就需要让React知道谁是孙悟空,谁又是唐僧。在React内部就设定了一个key属性,key属性可以作为React元素的唯一标识,和html中id类似。在创建一个列表时,我们可以为列表的每一个元素指定一个唯一的key,React就可以根据key而不是位置来比较元素,这样一来无论元素的位置如何改变,都不会导致过多的元素渲染,因为有了key以后,React就不再通过位置来比较两个元素了。

    上边的例子可以这样修改:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    const ele = <ul>{students.map(item => <li key={item}>{item}</li>)}</ul>
    
    • 1
    • 2

    添加了key属性以后警告就消失了,设置key还有一些要求:

    • key必须在当前列表的元素中是唯一的
    • 一个元素的key最好是固定的
    • key不需要全局唯一,只需在当前列表中唯一即可。

    元素的key最好是固定的,这里直接举个反例,有些场景我们会使用元素的索引为key像这种:

    const students = ['孙悟空', '猪八戒', '沙和尚'];
    const ele = <ul>{students.map((item, index) => <li key={index}>{item}</li>)}</ul>
    
    • 1
    • 2

    上例中,使用了元素的索引(index)作为key来使用,但这有什么用吗?没用!因为index是根据元素位置的改变而改变的,当我们在前边插入一个新元素时,所有元素的顺序都会一起改变,那么它和React中按顺序比较有什么区别吗?没有区别!而且还麻烦了,唯一的作用就是去除了警告。所以我们开发的时候偶尔也会使用索引作为key,但前提是元素的顺序不会发生变化,除此之外不要用索引做key。

  • 相关阅读:
    docker (二)-yum&二进制部署
    springboot 整合 dubbo 实现分组聚合
    基于 Eureka 的 Ribbon 负载均衡实现原理【SpringCloud 源码分析】
    pcl 点云网络 化 vtk Delaunay 点云网络化
    【AI学习】LLaMA 系列模型的进化(一)
    牛客周赛 Round 15 D 游游的树上边染红(树形dp)
    js的变量赋值的问题
    Jenkins Maven pom jar打包未拉取最新包解决办法,亲测可行
    <C++>多继承以及典型的菱形继承案例
    理论和实践详解RabbitMQ惰性/延迟队列(lazy queues)(带测试样例及分析)
  • 原文地址:https://blog.csdn.net/qq_43472877/article/details/128129420