目前为止,关于过渡我们已经讲到:
- 单个节点
- 同一时间渲染多个节点中的一个
那么怎么同时渲染整个列表,比如使用 v-for
?在这种场景中,使用 <transition-group>
组件。在我们深入例子之前,先了解关于这个组件的几个特点:
- 不同于
<transition>
,它会以一个真实元素呈现:默认为一个<span>
。你也可以通过tag
特性更换为其他元素。 - 内部元素 总是需要 提供唯一的
key
属性值
key的值应该和元素本身有关,而不是元素所在的位置,否则出现下面的问题,所有的添加和删除的过渡动画都是最后一个,因为只有最后一个元素的key改变了!!!!!
列表的进入/离开过渡
现在让我们由一个简单的例子深入,进入和离开的过渡使用之前一样的 CSS 类名。
<template>
<div>
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<transition-group
tag="p"
mode="out-in"
enter-active-class="animated fadeInUp"
leave-active-class="animated fadeOutUp"
>
<span v-for="item in items" v-bind:key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
</template>
<script>
export default {
name: "a9",
data() {
return {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10
}
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
}
</script>
<style scoped>
.list-item {
display: inline-block;
margin-right: 10px;
}
</style>
这个例子有个问题,当添加和移除元素的时候,周围的元素会瞬间移动到他们的新布局的位置,而不是平滑的过渡,我们下面会解决这个问题。
只需要加入v-move即可
<transition-group>
组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move
特性,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name
属性来自定义前缀,也可以通过 move-class
属性手动设置。
<transition-group
tag="p"
mode="out-in"
move-class="move-class"
enter-active-class="animated fadeInUp"
leave-active-class="animated fadeOutUp"
>
添加已经有了过渡效果,但是删除依然很僵硬,暂时没有找到办法
解决办法
必须在leave-active-class中设置绝对定位!!!!!!!!!!
<template>
<div>
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<transition-group
tag="p"
mode="out-in"
move-class="move-class"
enter-active-class="animated fadeInUp"
leave-active-class="animated fadeOutUp pos"
>
<span v-for="item in items" v-bind:key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
</template>
<script>
export default {
name: "a9",
data() {
return {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10
}
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
}
</script>
<style scoped>
.list-item {
display: inline-block;
margin-right: 10px;
}
.move-class{
transition: 1s;
}
.pos{
position: absolute;
}
</style>