Vue中key的作用与原理

一、引言

Vue中key的作用与原理
        日常开发中,我们经常会用到v-for指令,处理列表渲染等涉及动态元素增删改场景,为我们带来了遍历数组数据的便捷与高效。在使用v-for时,一个不可或缺的伙伴便是key属性,它的的作用和原理是什么呢?

二、key的作用与原理

key 作用 :用来作为节点的唯一标识

       当为一个列表绑定一个key属性时,该属性会存在于虚拟的DOM中,key是虚拟DOM对象的标识,当数据发生变化时,会生成新的虚拟DOM。随后Vue会使用Diff算法进行新虚拟DOM与旧虚拟DOM的差异比较。进行比较的过程可以分成两种情况:

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

三、情景举例

举例一:在v-for中不使用key属性(vue会把默认索引作为key的唯一标识)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>key的作用以及原理</title>
		<script src="vue.js"></script>
	</head>
	<body>
		<div id="app">
			<ul>
				<li v-for="(list,index) in  userinfo">{{list.username +"-"+  list.age}}</li>
			</ul>
			<button @click="add">点击添加信息</button>     
		</div>

		<script type="text/javascript">
			const vm = new Vue({
				el: "#app",
				data: {
					msg:{username:"赵六",age:20},
					userinfo: [{
						username: "张三",
						age: 17
					}, {
						username: "李四",
						age: 18
					}, {
						username: "王五",
						age: 19
					}]
				},
				methods:{
					add()  //用来点击向userinfo头部添加一条数据
					{
						this.userinfo.unshift(this.msg)
					}
				}
			})
		</script>
	</body>
</html>

运行结果如下图:

Vue中key的作用与原理
根据运行结果,大家可以看到不写key属性也能正常地显示我们想要的效果,所以为何要多加一个key属性呢?

       事实上,当你没有添加key属性时,系统会默认将绑定的key属性的值指向index(列表的索引),例如:{username:’张三’,age:17}的index值就为0,{username:’李四’,age:18}的index值就为1,依次类推,为每一个li标签加上标识。

举例二:在v-for中使用key属性

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>key的作用与原理</title>
       <script src="vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>人员列表</h2>
            <button @click.once="add">添加新用户</button>
            <ul>
                <!-- 绑定了key属性,并将其值指向于index -->
                <li v-for="(p,index) of persons" :key="index">
                    {{p.username}}-{{p.age}}&nbsp;&nbsp;&nbsp;&nbsp;
                    <!-- 增加了input输入框 -->
                   爱好: <input type="text">
                </li>
            </ul>
        </div>
        <script type="text/javascript">
            new Vue({
                el:'#root',
                data:{
                    persons:[
                        {id:'001',username:'张三',age:17},
                        {id:'002',username:'李四',age:18},
                        {id:'003',username:'王五',age:19}
                    ]
                },
                methods: {
                    add(){
                        const p = {id:'004',username:'赵六',age:20}
                        this.persons.unshift(p)
                    }
                },
            })
        </script>
</html>

Vue中key的作用与原理

Vue中key的作用与原理

      通过以上的运行结果我们可以很明显地看出问题,当爱好输入框没有内容时,添加之后并没有什么问题,但是当我们在添加新用户之前先输入现有用户的爱好时,我们会发现添加之后出现了输入框错乱的问题,为何会出现这种问题呢?

Vue中key的作用与原理

       当我们把index作为key时,初始数据之后会根据数据生成虚拟的DOM,对应的li标签中的key值分别是0,1,2。当数据生成初始虚拟DOM之后,会创建新的真实DOM,随后渲染到到页面。而当我们再添加一条数据时,会根据我们新的数据来生成新的虚拟DOM。新的虚拟DOM会与初始的也就是旧的虚拟DOM来进行对比,先找到对应相同的key值的li,若虚拟DOM中内容没变, 直接使用之前的真实DOM,若虚拟DOM中内容变了, 则生成新的真实DOM。

       对比发现key=”0″中的内容有变化,从“张三-17”变成了“赵六-20”,随后替换掉页面中之前的真实DOM。而爱好:<input type=”text”>对比的结果是相同的,因此保存原本的内容。key=”1″以及key=”2″以此类推。而key=”3″并没有在旧虚拟DOM中找到,因此创建新的真实DOM,随后渲染到到页面。

举例三:在v-for中使用数据唯一标识作为key值

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>key的作用与原理</title>
       <script src="vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>人员列表</h2>
            <button @click.once="add">添加新用户</button>
            <ul>
                <!-- 绑定了key属性,并将其值指向于index -->
                <li v-for="(p,index) of persons" :key="p.id">
                    {{p.username}}-{{p.age}}&nbsp;&nbsp;&nbsp;&nbsp;
                    <!-- 增加了input输入框 -->
                   爱好: <input type="text">
                </li>
            </ul>
        </div>
        <script type="text/javascript">
            new Vue({
                el:'#root',
                data:{
                    persons:[
                        {id:'001',username:'张三',age:17},
                        {id:'002',username:'李四',age:18},
                        {id:'003',username:'王五',age:19}
                    ]
                },
                methods: {
                    add(){
                        const p = {id:'004',username:'赵六',age:20}
                        this.persons.unshift(p)
                    }
                },
            })
        </script>
</html>

Vue中key的作用与原理

Vue中key的作用与原理

        我们可以明显地看出,若我们的key属性绑定的值为数据中的唯一标识时,我们就能够得到我们想要的结果。对应的原理图如下:

Vue中key的作用与原理
       每一个li标签中绑定的值为id,因此当添加一个新成员时,对应的key值为004,并没有在旧的虚拟DOM中找到,因此添加到真实的DOM中并渲染在页面上。其他的根据key值比较没有变化,保留原本的内容。

四、结语

若使用index作为key需要考虑如下两个问题:

  • 若对数据进行逆序添加、逆序删除等破坏顺序的操作时, 会产生没有必要的真实DOM更新 ,虽然界面效果没问题,但效率低;
  • 如果结构中还包含输入类的DOM,会产生错误DOM更新 ,界面会产生问题。

       我们在开发中,首先最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号等唯一值。 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,用index作为key是没有问题的。

参考文档:v2.cn.vuejs.org/v2/api/#key

v2.cn.vuejs.org/v2/guide/li…

原文链接:https://juejin.cn/post/7356852538719092745 作者:王小菲

(0)
上一篇 2024年4月14日 下午4:32
下一篇 2024年4月15日 上午10:00

相关推荐

发表回复

登录后才能评论