Vue中key有何用,在简单列表中用不用key
Admin 2022-09-14 群英技术资讯 729 次浏览
这篇文章主要介绍“Vue中key有何用,在简单列表中用不用key”,有一些人在Vue中key有何用,在简单列表中用不用key的问题上存在疑惑,接下来小编就给大家来介绍一下相关的内容,希望对大家解答有帮助,有这个方面学习需要的朋友就继续往下看吧。Vue中key的作用
key的特殊attribute主要用在Vue的虚拟DOM算法,在新旧Nodes对比时辨识VNodes。如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改、复用相同类型元素的算法,而使用key时,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。此外有相同父元素的子元素必须有独特的key,重复的key会造成渲染错误。
描述
首先是官方文档的描述,当Vue正在更新使用v-for渲染的元素列表时,它默认使用就地更新的策略,如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态的列表渲染输出,例如表单输入值。为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute,建议尽可能在使用v-for时提供key attribute,除非遍历输出的DOM内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
简单来说,当在列表循环中使用key时,需要使用key来给每个节点做一个唯一标识,diff算法就可以正确的识别此节点,找到正确的位置直接操作节点,尽可能地进行重用元素,key的作用主要是为了高效的更新虚拟DOM。此外,使用index作为key是并不推荐的做法,其只能保证Vue在数据变化时强制更新组件,以避免原地复用带来的副作用,但不能保证最大限度的元素重用,且使用index作为key在数据更新方面和不使用key的效果基本相同。
示例
首先定义一个Vue实例,渲染四个列表,分别为简单列表与复杂列表,以及其分别携带key与不携带key时对比其更新渲染时的速度,本次测试使用的是Chrome 81.0,每次在Console执行代码时首先会进行刷新重新加载界面,避免浏览器以及Vue自身优化带来的影响。
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in simpleListWithoutKey" >{{item}}</li>
</ul>
<ul>
<li v-for="item in simpleListWithKey" :key="item" >{{item}}</li>
</ul>
<ul>
<li v-for="item in complexListWithoutKey">
<span v-for="value in item.list" v-if="value > 5">{{value}}</span>
</li>
</ul>
<ul>
<li v-for="item in complexListWithKey" :key="item.id">
<span v-for="value in item.list" :key="value" v-if="value > 5">{{value}}</span>
</li>
</ul>
</div>
</body>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
simpleListWithoutKey: [1, 2, 3, 4, 5, 6],
simpleListWithKey: [1, 2, 3, 4, 5, 6],
complexListWithoutKey:[
{id: 1, list: [1, 2, 3]},
{id: 2, list: [4, 5, 6]},
{id: 3, list: [7, 8, 9]}
],
complexListWithKey:[
{id: 1, list: [1, 2, 3]},
{id: 2, list: [4, 5, 6]},
{id: 3, list: [7, 8, 9]}
],
}
})
</script>
</html>
简单列表
在简单列表的情况下,不使用key可能会比使用key的情况下在更新时的渲染速度更快,这也就是官方文档中提到的,除非遍历输出的DOM内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。在下面的例子中可以看到没有key的情况下列表更新时渲染速度会快,当不存在key的情况下,这个列表直接进行原地复用,原有的节点的位置不变,原地复用元素,将内容更新为5、6、7、8、9、10,并添加了11与12两个节点,而存在key的情况下,原有的1、2、3、4节点被删除,5、6节点保留,添加了7、8、9、10、11、12六个节点,由于在DOM的增删操作上比较耗时,所以表现为不带key的情况下速度更快一些。
// 没有key的情况下 console.time(); vm.simpleListWithoutKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() => console.timeEnd()); // default: 2.193056640625ms
// 存在key的情况下 console.time(); vm.simpleListWithKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() => console.timeEnd()); // default: 3.2138671875ms
原地复用可能会带来一些副作用,文档中提到原地复用这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态的列表渲染输出,例如表单输入值。在不设置key的情况下,元素中没有与数据data绑定的部分,Vue会默认使用已经渲染的DOM,而绑定了数据data的部分会进行跟随数据渲染,假如操作了元素位置,则元素中未绑定data的部分会停留在原地,而绑定了data的部分会跟随操作进行移动,在下面的例子中首先需要将两个A之后的输入框添加数据信息,这样就制作了一个临时状态,如果此时点击下移按钮,那么不使用key的组中的输入框将不会跟随下移,且B到了顶端并成为了红色,而使用key的组中会将输入框进行下移,且A依旧是红色跟随下移。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>就地复用</title>
</head>
<body>
<div id="app">
<h3>采用就地复用策略(vuejs默认情况)</h3>
<div v-for='(p, i) in persons'>
<span>{{p.name}}<span>
<input type="text"/>
<button @click='down(i)' v-if='i != persons.length - 1'>下移</button>
</div>
<h3>不采用就地复用策略(设置key)</h3>
<div v-for='(p, i) in persons' :key='p.id'>
<span>{{p.name}}<span>
<input type="text"/>
<button @click='down(i)' v-if='i != persons.length - 1'>下移</button>
</div>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
persons: [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' }
]
},
mounted: function(){
// 此DOM操作将两个A的颜色设置为红色 主要是为了演示原地复用
document.querySelectorAll("h3 + div > span:first-child").forEach( v => v.style.color="red");
},
methods: {
down: function(i) {
if (i == this.persons.length - 1) return;
var listClone = this.persons.slice();
var one = listClone[i];
listClone[i] = listClone[i + 1];
listClone[i + 1] = one;
this.persons = listClone;
}
}
});
</script>
</body>
</html>
<!-- 源于 https://www.zhihu.com/question/61078310 @霸都丶傲天 有修改-->
复杂列表
使用key不仅能够避免上述的原地复用的副作用,且在一些操作上可能能够提高渲染的效率,主要体现在重新排序的情况,包括在中间插入和删除节点的操作,在下面的例子中没有key的情况下重新排序会原地复用元素,但是由于v-if绑定了data所以会一并进行操作,在这个DOM操作上比较消耗时间,而使用key得情况则直接复用元素,v-if控制的元素在初次渲染就已经决定,在本例中没有对其进行更新,所以不涉及v-if的DOM操作,所以在效率上会高一些。
console.time();
vm.complexListWithoutKey = [
{id: 3, list: [7, 8, 9]},
{id: 2, list: [4, 5, 6]},
{id: 1, list: [1, 2, 3]},
];
vm.$nextTick(() => console.timeEnd());
vm.$nextTick(() => console.timeEnd());
// default: 4.100244140625ms
console.time();
vm.complexListWithKey = [
{id: 3, list: [7, 8, 9]},
{id: 2, list: [4, 5, 6]},
{id: 1, list: [1, 2, 3]},
];
vm.$nextTick(() => console.timeEnd());
// default: 3.016064453125ms
总结
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍了vant picker+popup 自定义三级联动案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
TypeScript引入了很多静态编译语言的特性,今天有一个类型需要着重讨论下,这就是enum,需要的朋友们下面随着小编来一起学习学习吧
本篇文章给大家带来了关于javascript的相关知识,其中主要介绍了关于JavaScript的push()、pop()、unshift()、shift() 方法的使用,下面一起来看一下,希望对大家有帮助。
在制作网页页面时,轮播图效果是比较常见的,想要实现轮播图效果的方法很多,本文主要介绍的使用jQuery实现轮播图,以下是实现代码,感兴趣的朋友可以了解看看。
这篇文章主要介绍了vue项目中 jsconfig.json是什么,本文仅仅简单介绍了 jsconfig .json 的一些基本配置,而 jsconfig .json提供了大量能使我们快速便捷提高代码效率的方法,需要的朋友可以参考下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008