若是没有这个属性的时候vue应用 in-place patch(就地复用)策略。列表里的顺序发生改变的时候好比shuffle(列表打乱)的时候,vue为了提高性能,不会移动dom元素,只是更新相应元素的内容节点。javascript
这个默认的模式是高效的,可是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。css
如上引用自官网,这个模式就是上面的“就地复用”策略。那么是否是依赖子组件状态的列表渲染采用上面的模式就出问题了呢。以下测试代码:html
<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>
复制代码
操做以下: vue
ps: 测试临时 DOM 状态 (例如:表单输入值)能够参考这个连接 List Rendering and Vue’s v-for Directivejava
这个时候引入 key
就能够解决这个问题。key
的做用是给予一个节点惟一的身份识别,有相同父元素的子元素必须有独特的 key
。这样它能够先后对比,算出哪些节点是要重复使用或者调整顺序。好比原先的 key
的顺序是i1,i2,i3
,以后变成了i2,i1,i3
这个时候只要i3保持不变,把i2insertBefore
到i1节点前就好了(以上是举例,vue具体怎么操做的须要去研究源码)。若是是利用数组的index
来做为 key
则两次对比没有区别,就会出现上面动图里出现的子组件没有更新的状况。web
能够经过查看下面两个动图查看dom节点的变化。第一个gif是没有使用 key
,第二个是使用了 key
。能够看到我点了按钮后,第一个只是更新<p>
标签的内容节点。第二个是移动了某一项的<li>
标签。chrome
ps: 另外能够经过chrome的dom断点功能查看子元素的插入删除。api
DOM 更改断点数组
key不是只能用在v-for上还能够用在其余元素上。以下代码app
<div v-if="toggle">Hello</div>
<div v-else>Goodbye</div>
复制代码
切换toggle时,它也是切换div。若是你想用上enter/leave animations时,即节点插入和删除的时候的动画时就要打破这个复用,以下:
<transition>
<div v-if="toggle" key="1">Hello</div>
<div v-else key="2">Goodbye</div>
</transition>
复制代码
若是你的列表不发生变化,或者你只是往列表最后一项添加元素则看似没必要要增长key
字段。可是你的项目中有不少列表的时候,你有的须要加key
,有的不须要加。还不如全部的都加上呢避免别人理解困难(^._.^)ノ。