Vue2入门之超详细教程十三-key的作用与原理

发布时间 2024-01-05 21:45:00作者: 李荣洋

Vue2入门之超详细教程十三-key的作用与原理

1、简介

React、Vue中的key有什么作用?

1.虚拟DOM中key的作用:

​ key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据[新数据]生成[新的虚拟DOM],随后Vue进行[新虚拟DOM]的差异比较,比较规则如下:

​ (1)旧虚拟DOM中找到了与新虚拟DOM相同的key

​ 若虚拟DOM中内容没变,直接使用之前的真实DOM

​ 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

​ (2)旧虚拟DOM中未找到与新虚拟DOM相同的key

​ 创建新的真实DOM,随后渲染到页面

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

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

​ (2)如果结构中还包含输入类DOM:会产生错误DOM更新 == >界面显示有问题

3.开发中如何选择key?

​ (1)最好使用每条数据的唯一表示作为key,比如id、手机号、省份证号、学号等唯一值

​ (2)如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表用于展示,使用index作为key是没有问题的

学习Vue之前最后会一些HTML和CSS的基础知识,HTML基础知识 传送门,CSS基础知识 传送门

2、key的原理

1. 问题演示

在vscode中创一个新目录,叫“12_列表渲染”,在下面创建一个“02_key的原理.html”文件,在里面输入以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>key的原理</title>
    <script type="text/javascript" src="../js/development/vue.js"></script>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="root">
        <!-- 遍历数组 -->
        <h2>人员列表(遍历数组)</h2>
        <!-- click.once表示只可以点击一次 -->
        <button @click.once="add">添加一个老刘</button>
        <ul>
            <li v-for="(p,index) of persons" :key="index">
                {{p.name}}-{{p.age}}
                
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTop=false
        new Vue({
            el:'#root',
            data:{
                persons:[
                    {id:'001',name:'张三',age:18},
                    {id:'002',name:'李四',age:19},
                    {id:'003',name:'王五',age:20},
                ]
            },
            methods:{
                add(){
                    const p = {id:'004',name:'老六',age:40}
                    // 添加在数组最前面
                    this.persons.unshift(p)
                }
            }
        })
    </script>
</body>
</html>

目的在于为数组新增一条数据,@click.once表示只执行一次,this.persons.unshift()表示在数组最前面增加数据

image-20240105210851504

目前看这功能实现的挺好,也没没什么问题,但是这有一个致命的问题,让我们搭配input输入框试试

<li v-for="(p,index) of persons" :key="index">
    {{p.name}}-{{p.age}}
    <input type="text">
</li>

来看看效果,大家可能很疑惑,这不挺好的吗,数据正常,点击新增按钮input输入框也展示正常,不着急我们在继续实验一下,首先在没有点击“添加一个老刘”按钮,时现在各个输入框输入内容,如下:

image-20240105211544845

此时在点击添加按钮

image-20240105211603984

这会效果就出来了,各个输入框对应的内容错位了,如果这样把数据传给后端,肯定不正确,那怎么办呢

2. 问题解决

在解决改问题之前首先说明一下产生的原因:这是因为我们用了:key="index"方式来进行数据排序,index会默认生成不同id分配给不同的数据,来验证一下:

<li v-for="(p,index) of persons" :a="index">

image-20240105212437400

可以看出,index就是0、1、2这样去递增,当我们像数据头插入一条数据时,0这个下标表示的数据就是“老六”了,input输入框不会变动,其他数据依次下移,就导致了该问题,想要解决该问题,需要给数据分配唯一的id

image-20240105213402609

<li v-for="(p,index) of persons" :key="p.id">

image-20240105212834785