详解如何理解vue的key属性

2020-06-14 06:14:14易采站长站整理

如果没有这个属性的时候vue应用 in-place patch(就地复用)策略。列表里的顺序发生改变的时候比如shuffle(列表打乱)的时候,vue为了提升性能,不会移动dom元素,只是更新相应元素的内容节点。

就地复用的弊端

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。

如上引用自官网,这个模式就是上面的“就地复用”策略。那么是不是依赖子组件状态的列表渲染采用上面的模式就出问题了呢。如下测试代码:


<ul>
<li v-for="item in items">
<p>{{ item.title }}</p>
<p>{{ item.des }}</p>
<tweet-component></tweet-component>
</li>
</ul>
<script>
Vue.component("tweet-component", {
template: `
<div class="tweet">
<div class="box">
{{xixi}}
</div>
</div>
`,
data() {
return {
xixi: Math.random()
};
}
});
new Vue({
el: "#app",
data: {
items: [
{ title: "nihao1", des: "xiexie1" },
{ title: "nihao2", des: "xiexie2" },
{ title: "nihao3", des: "xiexie3" }
] },
methods: {
shuffle() {
// lodash的shuffle方法
this.items = _.shuffle(this.items);
}
}
});
</script>

操作如下:

 

问题出现了:发生变化时,子组件 没有更新

ps: 测试临时 DOM 状态 (例如:表单输入值)可以参考这个链接 List Rendering and Vue’s v-for Directive

key的作用

这个时候引入

key
就可以解决这个问题。
key
的作用是给予一个节点唯一的身份识别,有相同父元素的子元素必须有独特的
key
。这样它可以前后对比,算出哪些节点是要重复使用或者调整顺序。比如原先的
key
的顺序是
i1,i2,i3
,之后变成了
i2,i1,i3
这个时候只要i3保持不变,把i2
insertBefore
到i1节点前就行了(以上是举例,vue具体怎么操作的需要去研究源码)。如果是利用数组的
index
来作为
key
则两次对比没有区别,就会出现上面动图里出现的子组件没有更新的情况。

可以通过查看下面两个动图查看dom节点的变化。第一个gif是没有使用