Vue中key的原理

key就是对节点进行一个标识。

在Vue中,以key为对比算法标识,在数据修改或更新后,通过key这个唯一标识进行对比虚拟DOM,从而决定节点的重新加载以及复用。


虚拟DOM

虚拟DOM 本质上是一个js对象 ,通过对象来表示真实的DOM结构。

key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据 新数据 生成 新的虚拟DOM


实例展示

现在,我们通过一个问题来展开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=\, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js -->
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <!-- 此时按钮只能点击一次 -->
        <button @click.once="add">添加人员(小明)</button>
        <!-- 遍历数组 -->
        <h2>人员列表(遍历数组)</h2>
        <ul>
            <li v-for="(p, index) in presons" :key="index">
                姓名:{{p.name}}-- 年龄{{p.age}}--
                备注:<input type="text">
            </li>
        </ul>
    </div>
</body>

<script>
    Vue.config.productionTip = false;

   const vm =  new Vue({
        el:'#app',
        data:{
            presons:[
                {id:'001', name:'张三', age:18},
                {id:'002', name:'李四', age:21},
                {id:'003', name:'王五', age:19},
            ]
        },
        methods: {
            add(){
                // 只有往前添加数据,才能看出问题
                const preson = {id:'004', name:'小明', age:12};
                this.presons.unshift(preson);
            }
        },
    })
</script>
</html>

在列表渲染中,使用的是index作为key,并没有选择data中的preson.id作为key
在这里插入图片描述

点击按钮添加人员信息:
在这里插入图片描述

为了能引出key的原理以及作用,再次我通过一个问题引出,假如每一个人的备注项输入框都输入上内容,然后再添加一个人员,就会存在以下问题

每个人的备注输入框都输入内容:
在这里插入图片描述

点击按钮添加人员信息:
在这里插入图片描述

此时我们会发现,当点击按钮添加信息后,备注项输入框内容发生了错误,添加人员后,备注项内容并没有跟随对应的节点,为什么出现这种情况呢,其实问题所在就是因为我们选用了index作为key,假如我们选用persons.id作为key,则不会出现此情况

使用persons.id作为key:
在这里插入图片描述

点击按钮添加人员信息:
在这里插入图片描述


那为什么选用index作为key?

在Vue中,存在虚拟DOM和对比算法,而对比算法的开展需要唯一标识作为对比前提,当我们选用index作为唯一标识时,其实Vue默认可以看做index是为下标索引,也就是说从0~n。和数组索引一样,当我们往节点第一位添加或更新数据时,其实新添加的数据索引为0,原有数据依次往后挪一位,这就导致在对比的时候,会出现原有信息错乱
虚拟DOM对比算法

在数据更新过后,新旧虚拟DOM会运用对比算法进行对比,而对比的前提就是key这个唯一标识符,通过key对比前后数据的变化,如果对比之后不一致的内容就不能复用, 只能把新的虚拟DOM转化为新的节点,当数据无改动时,则复用之前数据,然后再转化为真实DOM,也就是呈现在页面的内容。


虚拟DOM对比算法

Vue进行 新虚拟DOM旧虚拟DOM 的差异比较,比较规则如下:

  • 旧虚拟DOM中找到了与新虚拟DOM相同的key

            若虚拟DOM中内容没变,直接使用之前的真是DOM
            
            若虚拟DOM中的内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
    
  • 旧虚拟DOM中未找到与新虚拟DOM相同的key:

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

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

  • 若对数据进行:逆序添加、逆序删除等破坏顺序的操作:

      	会产生没有必要的真实DOM的更新 ==> 界面效果没什么问题,但是效率低
    
  • 如果结构中还包括输入类的DOM

      	会产生错误的DOM更新 ==> 界面有问题
    

开发中如何选择key?

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

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


总结

在Vue中,key的存在其作用就是在虚拟DOM转换为真实DOM这个过程中虚拟DOM新旧对比的前提,当然可以选择不同的唯一值来充当key,但是,无论在何种条件下,一定要考虑清除key唯一标识符,否则在虚拟DOM对比时,将出现错误,以至于导致页面呈现的内容出错,虚拟DOM就是为了解决浏览器性能问题而被设计出来的。而key的存在,又为虚拟DOM比较时,提高了一定量的效率和节省了一定量的内存。

在这里插入图片描述

创作不易,记得点赞收藏,关注博主不迷路哟~~

Logo

前往低代码交流专区

更多推荐