【React 全家桶】React 中虚拟DOM的 key(diff 算法)(伴随经典面试题)

一、经典面试题

1、React 中虚拟DOM的key有什么作用?(key的内部原理是什么?)
2、为什么遍历列表时,key最好不要用index?

二、虚拟DOM中key的作用

当状态中的数据发生变化时,React会根据【新数据】生产【新的虚拟DOM】,然后React使用diff算法对比【新虚拟DOM】和【旧虚拟DOM】,规则如下:
1.【旧虚拟DOM】中找到了与【新虚拟DOM】相同的key:
    a.若虚拟DOM的内容没变,直接使用之前的真实DOM
    b.若虚拟DOM的内容变了,则生产新的真实DOM,随后替换掉页面中之前真实DOM
2.【旧虚拟DOM】中未找到与【新虚拟DOM】相同的key:
    根据数据创建新的真实DOM,随后渲染到页面

三、用index作为key可能引发的问题

1、若对数据进行:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 页面效果没有问题,但效率低。

2、如果结构中包括输入类(input等)的DOM,会产生错误的DOM更新 ==>页面有问题

3、注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表的话,使用index作为key时没有问题的。

代码案例1:如果使用index作为key,实现逆序添加的需求—页面没有问题,但效率低

<!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>案例1-无输入类</title>
</head>

<body>
    <!-- 创建一个容器 -->
    <div id="test"></div>
    <!-- 引入react核心库 -->
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作dom -->
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <!-- 引入bable,将jsx转化为js -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <!-- 表示写的是jsx -->
    <script type="text/babel">
        // 1.创建类式组件
        class Demo extends React.Component {
            state = { person: [{ id: 1, name: '小张' }, { id: 2, name: '小李' }] }
            add = () => {
                let { person } = this.state;
                let obj = {
                    id: 3,
                    name: '小王'
                }
                //逆序添加
                person.unshift(obj);
                this.setState({ person: person });
            }
            //render放在类的原型对象上
            render() {
                const { person } = this.state;
                return (
                    <div>
                        <h1>案例1-无输入类</h1>
                        <button onClick={this.add}>逆序添加</button>
                        <ul>
                            {
                                person.map((item, index) => {
                                    return <li key={index}>{item.id}{item.name}</li>
                                })
                            }
                        </ul>
                    </div>
                )
            }
        }
        ReactDOM.render(<Demo id="id属性" />, document.querySelector('#test'));
    </script>
</body>

</html>

在这里插入图片描述

代码案例2:如果使用index作为key,对含有输入类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>案例2-有输入类</title>
</head>

<body>
    <!-- 创建一个容器 -->
    <div id="test"></div>
    <!-- 引入react核心库 -->
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作dom -->
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <!-- 引入bable,将jsx转化为js -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <!-- 表示写的是jsx -->
    <script type="text/babel">
        // 1.创建类式组件
        class Demo extends React.Component {
            state = { person: [{ id: 1, name: '小张' }, { id: 2, name: '小李' }] }
            add = () => {
                let { person } = this.state;
                let obj = {
                    id: 3,
                    name: '小王'
                }
                //逆序添加
                person.unshift(obj);
                this.setState({ person: person });
            }
            //render放在类的原型对象上
            render() {
                const { person } = this.state;
                return (
                    <div>
                        <h1>案例2-有输入类</h1>
                        <button onClick={this.add}>逆序添加</button>
                        <ul>
                            {
                                person.map((item, index) => {
                                    return <li key={index}>{item.id}{item.name} <input type="text"/></li>
                                })
                            }
                        </ul>
                    </div>
                )
            }
        }
        ReactDOM.render(<Demo id="id属性" />, document.querySelector('#test'));
    </script>
</body>

</html>

在这里插入图片描述
输入框发生错乱,所以这里key肯定是要使用唯一标识

四、开发中如何选择key

1、最好使用每条数据的唯一标识作为key,比如id、手机号、身份证、学号等

2、如果确定只是简单的展示数据,用index也是可以的。

以上就是React 中虚拟DOM中key的内容,请大家关注《React 全家桶》专栏。
我会将自己平时项目中常见的问题以及笔试面试的知识在CSDN与大家分享,一起进步,加油。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Dai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值