对v-for就地复用概念的一点理解

作者 likaiqiang 日期 2017-03-26
对v-for就地复用概念的一点理解

本来今天是要去试着用vuejs的思想去写一个轮播的,但却意外的发现了另一个问题。

<div id="app">
<transition-group tag='ul' name='move'>
<li v-for='(item,index) in arr' :key='index' v-if='index==currentIndex'></li>
</transition-group>
<button @click='pre'>pre</button>
<button @click='next'>next</button>
</div>
new Vue({
el:'#app',
data(){
return {
isMove:true,
arr:[1,2,3],
currentIndex:0
}
},
methods:{
toggle(){
this.isMove = !this.isMove;
},
pre(){
this.currentIndex--;
if(this.currentIndex==-1)
this.currentIndex=0;
},
next(){
this.currentIndex++;
if(this.currentIndex==this.arr.length)
this.currentIndex=this.arr.length-1;
}
}
})
.box{
width:100px;
height:100px;
background:yellowgreen;
}
li{
width:80px;
height:80px;
background:yellowgreen;
list-style:none;
display:inline-block;
margin-right:10px;
}
.move-enter{
opacity:0;
}
.move-enter-active,.move-leave-active{
transition:all 1s;
}
.move-leave-active{
opacity:0;
}

简单录了一个gif图,第一次录,不太会弄,忽略掉难看的动效直接看问题

咱理一下思路,按照双向绑定的逻辑,我每点击pre或者next按钮,currentIndex会变,同时v-for会重新渲染列表。这样想的话,应该只会有dom添加,不会有dom删除。对应到动画渲染上,应该只会触发enter,不会触发leave。可是实际上,两个都触发了。

为什么会这样,看看vue官方是怎样解释v-for

结合上面的问题,文档的意思应该是:当v-for所循环的每一项顺序发生改变时,vue不是重新更新整个dom,而是简单的复用每个元素来达到目的。对应到这个例子上,当currentIndex发生改变时(假如改变前currentIndex=0,改变后currentIndex=1),vue不会重新渲染整个循环列表,而是先删除currentIndex=0时渲染的li,触发leave动画,再增加currentIndex=1时渲染的li,触发enter动画,这样就合理了。