刚刚接触了 Vue三天 ,用Vue 做了todoMVC 这个入门经典案例。
在我为这个案例编写完成而高兴时,在 active 和 completed 这个两个模块中发现了问题。
按思路来讲 Active 模块中存放的都是已完成的任务,当我在圆形 checkbox 中勾选时对应的条目应该消失,变成已完成项目 。不应该像上图所示有对号的样式残留。
再我找了好久之后,才发现原来是在编写 "v-for" 循环时为 标签动态绑定的key是数组下标。在我绑定 :key的是每个对象的id即唯一标识时这个问题就迎刃而解了。
下面就来谈一谈 "v-for"的key值问题。
我们先写一个简单的实例
<body>
<div id="app">
<h2>人员列表</h2>
<ul >
<button @click="add">添加一个老刘</button>
<li v-for="(item,index) in persons" :key="index">
{{item.name}}--{{item.age}} <input type="text">
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
persons:[
{id:"001",name:"张三",age:18},
{id:"002",name:"李四",age:19},
{id:"003",name:"王五",age:20}
],
newP:{id:"004",name:"老刘",age:30}
},
methods: {
add(){
this.persons.unshift(this.newP)
}
},
})
</script>
</body>
在我点击button按钮效果如下没有任何问题
但是我在每个输入框写入每个人的·信息后在点击添加按钮却出现了问题。
点击之前:
点击之后:
我们可以看到每个人的信息出现了不匹配的问题,但是当我吧:key="index"改为:key="item.id"
再次运行:
样式正常了。这是为什么呢?
因为 key 是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据新数据生成新的虚拟DOM ,随后Vue进行虚拟DOM与旧虚拟DOM差异进行比较
那么是怎样进行比较的呢?
一、旧虚拟DOM找到了与新虚拟DOM相同的Key :
- 若虚拟DOM内容没有变,则会直接使用之前的真实DOM
- 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面之前的真实DOM。
二、旧虚拟DOM中未找到与新虚拟DOM相同的key:
- 创建新的真实DOM,随后渲染到页面
用 index 作为key的遍历原理:
用 id作为key的遍历原理:
那在使用过程中如何选择key?:
- 最好使用每条数据的唯一标识作为key,比如id,手机号,身份证号,学号等唯一值。
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染展示,使用index作为key是没有问题的。