本文改写整理自一篇博文,原文链接如下:

Why you should use the key directive in Vue.js with v-for

Application state and DOM state

要回答这个问题,我们先要了解一下以下两个概念:应用状态(Application state)和 DOM 状态(DOM state),先创建一个简单的 Vue 组件如下(Vue 3):

<script setup>
import { reactive } from "@vue/reactivity" let list = reactive([
{
name: 'name1',
likes: '炸鸡汉堡',
id: 'item1',
},
{
name: 'name2',
likes: '红茶枸杞',
id: 'item2'
}
]); // 用来调换列表顺序
const changeOrder = () => {
let list2 = [...list];
list[0] = list2[1];
list[1] = list2[0];
}
</script> <template>
<ul class="list">
<li v-for="item in list"> <!-- 没有绑定 key -->
{{ item.name }} <br>
{{ item.likes }}
<input type="text">
</li>
</ul>
<button @click="changeOrder">改变列表顺序</button>
</template> <style scoped>
button {
margin-top: 1em;
}
</style>

此时界面如下:



我们可以在“红茶枸杞”后输入文本,例如“好喝”



然后点击“改变列表顺序”,我们可以看到界面变成这个样子:



很奇怪是不是?让我们来看看是为什么?

在这个例子里,每一条数据显示的 name 和 likes 的内容是从应用的状态(application state)里获得的,其余部分的内容没有和 Vue 实例里的任何数据绑定,因此是独立于应用状态的,所以你在 input 输入框内输入的东西是临时储存于 DOM 状态(DOM State)内的


In-place patch strategy

我们已经知道了应用状态和 DOM state 的区别,现在我们要理解一下 Vue 在渲染列表数据时所采取的策略,根据 Vue 的官网介绍:

When Vue is updating a list of elements rendered with v-for, by default it uses an "in-place patch" strategy. If the order of the data items has changed, instead of moving the DOM elements to match the order of the items, Vue will patch each element in-place and make sure it reflects what should be rendered at that particular index.

也就是说,在应用状态有变化的时候(例如列表的顺序变了),Vue 会尽可能小地减少 DOM 操作,尽可能地重用 DOM, 在上述例子里,Vue 只会更新 DOM 元素内的状态,而不是真的把两个 <li> 标签交换位置,以此来反映应用状态的变化,我们可以通过下面这张 gif 来直观地感受下:

在上面的例子里,我们在输入框内输入的内容没有和如何应用状态绑定过,只是临时的 DOM 状态,又由于 Vue 的渲染策略,导致了我们在改变元素顺序时,input 并没有如我们想象中那样移动。

解决办法:添加 key

<li v-for="item in list" :key="item.id"> <!-- 绑定了 key -->

此时再点击更改列表顺序的按钮,可以看到 input 也会随着一起移动:

这里有一点需要注意,如果我们用数组的下标作为 key 的值,input 仍是不会移动的,数组的下标不是应用状态的一部分

<li v-for="(item, idx) in list" :key="idx"> <!-- 绑定了 key, 使用数组下标 -->

为什么你需要在用 Vue 渲染列表数据时指定 key的更多相关文章

  1. 【vue】渲染大量数据时性能优化

    对应vue渲染大量数据时可以考虑下面几点: 1. 异步渲染组件:因为组件渲染太多,影响页面的渲染时间,所有可以延迟组件渲染,可以考虑v-if处理 2. 可以使用虚拟滚动的组件:参考使用这个插件 vue ...

  2. React.js 小书 Lesson13 - 渲染列表数据

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson13 转载请注明出处,保留原文链接和作者信息. 列表数据在前端非常常见,我们经常要处理这种类型 ...

  3. 获取列表数据时,getList 设置默认参数:getList(page = 1),点击分页及前往时,传page参数,其他使用page的默认值:1

    获取列表数据时,getList 设置默认参数:getList(page = 1),点击分页及前往时,传page参数,其他使用page的默认值:1

  4. Vue渲染列表,在更新data属性后,列表未更新问题

    初始化代码如下var tableModel = new Vue({el: '#datatable',data: {items: listData}}); 当我对列表操作时,listData=>n ...

  5. 好客租房41-react组件基础综合案例-渲染列表数据

    1渲染列表 在state定义数据 进行数据渲染 //导入react import React from 'react' import ReactDOM from 'react-dom' //导入组件 ...

  6. Vue 基本列表 && 数据过滤与排序

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  7. vue再页面渲染json数据时没有显示

    对象点属性不能获取数据. 原因: 在创建数据对象时我使用了k,v方式:tempMap['category '] = this.category[i].label 如果在创建数据时使用的k,v方式,那么 ...

  8. vue v-for 遍历循环时的key值的报错

    问题如下: [Vue warn] Avoid using non-primitive value as key, use string/number value instead. non-primit ...

  9. Vue.js的列表数据的同步更新方法

    这次给大家带来Vue.js的列表数据的同步更新方法,Vue.js列表数据同步更新方法的注意事项有哪些,下面就是实战案例,一起来看一下. 数组的 push(),pop(),shift(),unshift ...

随机推荐

  1. c++ Message与Folder 拷贝 析构(没有动态空间的类)

    c++ Message与Folder 拷贝 析构(没有动态空间的类) 1.两个类里边分别保存一个对方的set表,当前类有拷贝或者销毁时需要更新另一个类的set表. 2.两个类都需要访问对方的priva ...

  2. Vue 源码解读(1)—— 前言

    当学习成为了习惯,知识也就变成了常识. 感谢各位的 点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/blog ...

  3. Welcom to my studyspace! 欢迎来到我的学习空间!

    由于新手,博客才刚开始起步,用于记录我的学习,博客的建设后续需要将其完善 对我的博客进行diy 用于分享我的学习经历,一些笔记,还有一些小小的心得

  4. 什么,有狗快跑!慢着,这次手把手教你怎么过安全狗!(sql注入篇)

    前言 在记忆里上次绕安全狗还是在上次,开开心心把自己之前绕过狗的payload拿出来,发现全部被拦截了,事情一下子就严肃起来了,这就开整. 环境 本次环境如下sqli-lab的sql注入靶场 网站安全 ...

  5. DDD与数据事务脚本

    DDD与数据事务脚本 扯淡 相信点进来看这篇文章的同学,大部分是因为标题里面的"DDD"所吸引!DDD并不是一个新技术,如果你百度一下它的历史就会知道,实际上它诞生于2004年, ...

  6. Renix软件如何建立OSPF邻居——网络测试仪实操

    OSPF可以通过OSPF向导的方式方便的创建OSPF邻居, 也可以通过纯手工的方式创建OSPF邻居, 本文介绍的是纯手工的方式创建. 在工作中, 推荐使用OSPF向导的方式来创建, 会比较简单和高效. ...

  7. BI企服界大众点评来袭!Smartbi入围36氪企服软件系列三大榜单!

    近日,36氪企服点评中国商业智能BI金榜揭晓.作为国产民族BI软件的领跑者,思迈特软件凭借深耕多年大数据BI领域中拥有过硬的产品实力与优质的服务,荣获"商业智能BI最佳软件总榜TOP10&q ...

  8. 华为RH2288H服务器引导ServiceCD安装Windows Server操作系统

    安装准备 ServiceCD光盘. Windows操作系统安装光盘. 物理光驱. 使用虚拟控制台远程安装操作系统时,需要准备以下软件: ServiceCD光盘或ServiceCD ISO文件. Win ...

  9. 网络中delay和latency的区别

    时序分析基本概念是Latency, 时钟传播延迟.主要指从Clock源到时序组件Clock输入端的延迟时间.它可以分为两个部分:时钟源插入延迟(source latency)和时钟网络延迟(netwo ...

  10. 【C# 程序集】C# assembly和module 根本区别

    相同点 两者都有:manifest.metadata.IL 不同点 1.assembly 有main程序函数.module只能附属于程序集,程序集可以拥有多个. 2.metadata的差异 程序集特有 ...