目录
为什么 v-for 的 key 值不能是 index?
总结
首页 web前端 Vue.js vue中为什么v-for指令的 key 值不能是 index?

vue中为什么v-for指令的 key 值不能是 index?

Jan 22, 2022 pm 03:05 PM
key v-for vue

vue中使用v-for时为什么不能用index作为key?下面本篇文章给大家介绍一下 v-for 的 key 值不能是 index 的原因,希望对大家有所帮助!

vue中为什么v-for指令的 key 值不能是 index?

为什么 v-for 的 key 值不能是 index?

很多人一说起这道老生常谈的面试题,马上就开始滔滔不绝地讲述 虚拟DOMdiff算法 了。

讲这些没问题,但如果是我,一定先讲 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: &#39;第1个元素&#39;
    },
    {
      count: 2,
      name: &#39;第2个元素&#39;
    },
    {
      count: 3,
      name: &#39;第3个元素&#39;
    }
  ]
  
handleDelete(index) {
  this.list.splice(index, 1)
},
登录后复制

1.gif

如代码和gif演示,点击删除第2个元素,看上去似乎一切正常。

等一下,第三个元素的count值居然变成了2,wtf!!!

惊得我又去看了遍子组件的代码

子组件
<div>
  <span>{{ name }}</span>
  count值为:{{ innerCount }}
  <button @click="$emit(&#39;delete&#39;)">-</button>
</div>

props: {
  count: {
    type: Number,
    default: 0
  },
  name: {
    type: String,
    default: &#39;&#39;
  }
},
data() {
  return {
    innerCount: this.count
  } 
}
登录后复制

感觉也没什么不对的啊。

不信邪,我又多创建了点元素来删除,还试了下排序:

2.gif

果然,不光删除元素有问题,排序也有问题。

把 key 值改成 item.name 再试一下。

<Child
  v-for="(item, index) in list"
  :key="item.name"
  :count="item.count"
  :name="item.name"
  @delete="handleDelete(index)"
/>
登录后复制

3.gif

正常了。

这样看来,在 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>
登录后复制

4.gif

删除了第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中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

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

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

vue怎么给按钮添加函数 vue怎么给按钮添加函数 Apr 08, 2025 am 08:51 AM

可以通过以下步骤为 Vue 按钮添加函数:将 HTML 模板中的按钮绑定到一个方法。在 Vue 实例中定义该方法并编写函数逻辑。

vue中怎么用bootstrap vue中怎么用bootstrap Apr 07, 2025 pm 11:33 PM

在 Vue.js 中使用 Bootstrap 分为五个步骤:安装 Bootstrap。在 main.js 中导入 Bootstrap。直接在模板中使用 Bootstrap 组件。可选:自定义样式。可选:使用插件。

vue中的watch怎么用 vue中的watch怎么用 Apr 07, 2025 pm 11:36 PM

Vue.js 中的 watch 选项允许开发者监听特定数据的变化。当数据发生变化时,watch 会触发一个回调函数,用于执行更新视图或其他任务。其配置选项包括 immediate,用于指定是否立即执行回调,以及 deep,用于指定是否递归监听对象或数组的更改。

vue.js怎么引用js文件 vue.js怎么引用js文件 Apr 07, 2025 pm 11:27 PM

在 Vue.js 中引用 JS 文件的方法有三种:直接使用 &lt;script&gt; 标签指定路径;利用 mounted() 生命周期钩子动态导入;通过 Vuex 状态管理库进行导入。

vue多页面开发是啥意思 vue多页面开发是啥意思 Apr 07, 2025 pm 11:57 PM

Vue 多页面开发是一种使用 Vue.js 框架构建应用程序的方法,其中应用程序被划分为独立的页面:代码维护性:将应用程序拆分为多个页面可以使代码更易于管理和维护。模块化:每个页面都可以作为独立的模块,便于重用和替换。路由简单:页面之间的导航可以通过简单的路由配置来管理。SEO 优化:每个页面都有自己的 URL,这有助于搜索引擎优化。

vue返回上一页的方法 vue返回上一页的方法 Apr 07, 2025 pm 11:30 PM

Vue.js 返回上一页有四种方法:$router.go(-1)$router.back()使用 &lt;router-link to=&quot;/&quot;&gt; 组件window.history.back(),方法选择取决于场景。

怎样查询vue的版本 怎样查询vue的版本 Apr 07, 2025 pm 11:24 PM

可以通过以下方法查询 Vue 版本:使用 Vue Devtools 在浏览器的控制台中查看“Vue”选项卡。使用 npm 运行“npm list -g vue”命令。在 package.json 文件的“dependencies”对象中查找 Vue 项。对于 Vue CLI 项目,运行“vue --version”命令。检查 HTML 文件中引用 Vue 文件的 &lt;script&gt; 标签中的版本信息。

vue函数怎么传参数 vue函数怎么传参数 Apr 08, 2025 am 07:36 AM

向 Vue.js 函数传递参数有两种主要方法:使用插槽传递数据或使用 bind 绑定函数,并提供参数:使用插槽传递参数:在组件模板中传递数据,在组件内访问并用作函数的参数。使用 bind 绑定传递参数:在 Vue.js 实例中绑定函数,并提供函数参数。

See all articles