vue中使用v-for时为什么不能用index作为key?下面本篇文章给大家介绍一下 v-for 的 key 值不能是 index 的原因,希望对大家有所帮助!
为什么 v-for 的 key 值不能是 index?
很多人一说起这道老生常谈的面试题,马上就开始滔滔不绝地讲述 虚拟DOM
和 diff算法
了。
讲这些没问题,但如果是我,一定先讲 v-for 的 key 值写成 index 会造成的问题,再讲原理。
曾经我写 v-for, key 值永远都是 index,直到有一天,我这么写造成了线上bug...
来看一下我的线上bug演示吧:
父组件代码 <Child v-for="(item, index) in list" :key="index" :count="item.count" :name="item.name" @delete="handleDelete(index)" /> list: [ { count: 1, name: '第1个元素' }, { count: 2, name: '第2个元素' }, { count: 3, name: '第3个元素' } ] handleDelete(index) { this.list.splice(index, 1) },
如代码和gif演示,点击删除第2个元素,看上去似乎一切正常。
等一下,第三个元素的count值居然变成了2,wtf!!!
惊得我又去看了遍子组件的代码
子组件 <div> <span>{{ name }}</span> count值为:{{ innerCount }} <button @click="$emit('delete')">-</button> </div> props: { count: { type: Number, default: 0 }, name: { type: String, default: '' } }, data() { return { innerCount: this.count } }
感觉也没什么不对的啊。
不信邪,我又多创建了点元素来删除,还试了下排序:
果然,不光删除元素有问题,排序也有问题。
把 key 值改成 item.name 再试一下。
<Child v-for="(item, index) in list" :key="item.name" :count="item.count" :name="item.name" @delete="handleDelete(index)" />
正常了。
这样看来,在 v-for 里把 key 值写成 index,非常危险啊。
在查阅了 vue 官方文档之后,我终于明白了原因:
当 Vue 正在更新使用
v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
不依赖子组件状态
子组件里有一行很关键的代码
data() { return { innerCount: this.count } }
子组件内部定义了 innerCount,这样子组件就有了自己的状态,按照官方文档的说明,这种情况下不能把 index 作为 key 值。
临时 DOM 状态
<div v-for="(item, index) in list1" :key="index"> <input type="text" /> <button @click="delClick(index)">删除</button> </div>
删除了第2项,但是第3项在表单中的3变成了2,跟上面依赖子组件状态的例子是一样的。
总结
写列表渲染时, 依赖子组件状态或临时 DOM 状态的情况,如果有 删除、增加、排序这样的功能,不要把 index 作为 key。
事实上,写列表渲染时,永远不要把 index 做为 key,key 一定要是唯一标识。
至于原因,就要理解 diff
算法之后才能明白了。
待解答问题:
- key 为什么不能写成随机数或时间戳?
- key 为什么要是唯一标识?
别着急,立了个写100个 vue 问题相关文章的 flag 呢,后面的文章再慢慢分析。
希望我的 vue 系列文章能对前端路上的你有帮助~
【相关推荐:vue.js视频教程】
以上是vue中为什么v-for指令的 key 值不能是 index?的详细内容。更多信息请关注PHP中文网其他相关文章!

Vue.js是一种渐进式JavaScript框架,适用于构建复杂的用户界面。1)其核心概念包括响应式数据、组件化和虚拟DOM。2)实际应用中,可以通过构建Todo应用和集成VueRouter来展示其功能。3)调试时,建议使用VueDevtools和console.log。4)性能优化可通过v-if/v-show、列表渲染优化和异步加载组件等实现。

Vue.js适合小型到中型项目,而React更适用于大型、复杂应用。1.Vue.js的响应式系统通过依赖追踪自动更新DOM,易于管理数据变化。2.React采用单向数据流,数据从父组件流向子组件,提供明确的数据流向和易于调试的结构。

Vue.js适合中小型项目和快速迭代,React适用于大型复杂应用。1)Vue.js易于上手,适用于团队经验不足或项目规模较小的情况。2)React的生态系统更丰富,适合有高性能需求和复杂功能需求的项目。

实现 Vue 中 a 标签跳转的方法包括:HTML 模板中使用 a 标签指定 href 属性。使用 Vue 路由的 router-link 组件。使用 JavaScript 的 this.$router.push() 方法。可通过 query 参数传递参数,并在 router 选项中配置路由以进行动态跳转。

Vue 中实现组件跳转有以下方法:使用 router-link 和 <router-view> 组件进行超链接跳转,指定 :to 属性为目标路径。直接使用 <router-view> 组件显示当前路由渲染的组件。使用 router.push() 和 router.replace() 方法进行程序化导航,前者保存历史记录,后者替换当前路由不留记录。

Vue 中 div 元素跳转的方法有两种:使用 Vue Router,添加 router-link 组件。添加 @click 事件监听器,调用 this.$router.push() 方法跳转。

Vue.js提供了三种跳转方式:原生 JavaScript API:使用 window.location.href 进行跳转。Vue Router:使用 <router-link> 标签或 this.$router.push() 方法进行跳转。VueX:通过 dispatch action 或 commit mutation 来触发路由跳转。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

SublimeText3汉化版
中文版,非常好用

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。