Vue 列表渲染默认复用 DOM 导致的问题
【摘要】 ❌ 问题场景:表单输入错乱假设我们有一个列表,渲染两个输入框,用户可以在输入框中输入内容:<template> <div> <button @click="swapItems">交换列表顺序</button> <div v-for="(item, index) in list" :key="index"> <input :placeholder="item.plac...
❌ 问题场景:表单输入错乱
假设我们有一个列表,渲染两个输入框,用户可以在输入框中输入内容:
<template>
<div>
<button @click="swapItems">交换列表顺序</button>
<div v-for="(item, index) in list" :key="index">
<input :placeholder="item.placeholder">
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, placeholder: "请输入姓名" },
{ id: 2, placeholder: "请输入年龄" }
]
};
},
methods: {
swapItems() {
// 交换列表中两项的顺序
this.list.reverse();
}
}
};
</script>
操作步骤:
- 用户在第一个输入框(“请输入姓名”)输入
"张三",在第二个输入框(“请输入年龄”)输入"25"。 - 点击“交换列表顺序”按钮,
list数组顺序被反转。 - Vue 默认会复用 DOM 元素(因为
key用了index,而索引0和1只是交换了位置)。
问题表现:
- 用户输入的内容 会跟着 DOM 元素移动,导致:
- 原本输入
"张三"的输入框(第一个)现在变成了"25"(因为复用了第二个<input>)。 - 原本输入
"25"的输入框现在变成了"张三"。
- 原本输入
- 用户看到的输入内容突然交换了,但实际数据(
list)并没有变,只是 DOM 被复用了。
🔍 原因分析
Vue 默认通过 key 来判断是否复用 DOM 元素:
- 如果
key是index(如:key="index"),交换数组顺序后,索引0和1只是换了位置,Vue 会认为这两个<input>可以直接复用,只是移动了位置。 - 但
<input>的当前值(用户输入的内容)是 DOM 的临时状态,Vue 不会自动帮你保存或同步它! - 结果就是:输入框的值跟着 DOM 元素移动,导致错乱。
✅ 正确做法:唯一 key + 数据驱动
方法 1:用唯一 id 作为 key,并避免依赖 DOM 状态
<template>
<div>
<button @click="swapItems">交换列表顺序</button>
<div v-for="item in list" :key="item.id">
<!-- 用 item.id 作为 key,且输入值绑定到数据 -->
<input :placeholder="item.placeholder" v-model="item.value">
</div>
<p>当前数据:{{ list }}</p>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, placeholder: "请输入姓名", value: "" },
{ id: 2, placeholder: "请输入年龄", value: "" }
]
};
},
methods: {
swapItems() {
this.list.reverse(); // 交换顺序
}
}
};
</script>
关键改进:
key使用唯一标识(item.id):- Vue 能准确知道每个列表项的身份,不会错误复用 DOM。
- 输入值绑定到数据(
v-model):- 用户输入的内容会实时同步到
list的value字段,而不是依赖 DOM 的临时状态。
- 用户输入的内容会实时同步到
- 交换顺序后:
- Vue 会根据
key重新匹配 DOM 元素,但输入值已经保存在数据中,不会错乱。
- Vue 会根据
📌 总结
| 问题场景(错误) | 正确做法 |
|---|---|
用 index 作为 key |
用唯一 id 作为 key |
依赖 DOM 临时状态(如 <input> 的当前值) |
用 v-model 绑定到数据 |
| 交换顺序后输入框内容错乱 | 数据和 DOM 正确同步,无错乱 |
核心原则:
- Vue 的默认复用策略要求列表渲染结果不依赖 DOM 的临时状态。
- 如果列表项有交互(如表单输入),必须用
v-model绑定数据,并用唯一key确保正确复用。
这样就能避免“输入内容突然跑到其他输入框”的诡异问题了!
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)