深入剖析列表过渡
一、深入剖析列表过渡
1.过渡_列表过渡
当想要给一个列表添加过渡动效时,我们可以使用 <transition-group>
组件。
//App.vue
<template>
<div id="app">
<base-level >
</base-level>
</div>
</template>
<script>
import BaseLevel from './components/BaseLevel1';
export default {
name: 'App',
components: {
BaseLevel
},
}
</script>
//BaseLevel1
<template>
<div class="demo">
<button @click="show = !show">click</button>
<transition-group>
<div key="world" v-if="show">hello wrold</div>
<div key="shanshan" v-if="show">hello shanshan</div>
</transition-group>
</div>
</template>
<script>
export default {
data () {
return {
show: true
}
}
}
</script>
<style scoped>
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: all .3s;
}
.v-leave,
.v-enter-to {
opacity: 1;
}
</style>
该组件的特点:
- 不同于 ,它会以一个真实元素呈现:默认为一个 。你也可以通过 tag attribute 更换为其他元素。
- 过渡模式不可用,因为我们不再相互切换特有的元素。
- 内部元素 总是需要 提供唯一的 key 属性值。
- CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。
<template>
<div class="demo">
<button @click="handleAdd">添加</button>
<button @click="handleRemove">移除</button>
<button @click="handleShuffle">洗牌</button>
<br />
<transition-group tag="ul">//替换成ul
<li
v-for="item in lists"
:key="item"
>{
{
item }}</li>
</transition-group>
</div>
</template>
<script>
export default {
data () {
return {
lists: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
nextNum: 11,
}
},
methods: {
handleAdd () {
const randomIndex = Math.floor( Math.random() * this.lists.length );
this.lists.splice(randomIndex, 0, this.nextNum ++);
},
handleRemove () {
const randomIndex = Math.floor( Math.random() * this.lists.length );
this.lists.splice(randomIndex, 1);
},
handleShuffle () {
this.lists.sort(() => Math.random() - 0.5);
},
},
}
</script>
2.列表的排序过渡
<transition-group>
组件提供了一个新的特性:v-move,它会在元素改变定位的过程中应用。
如何使用?通过类名即可设置:.v-move {}。
当给 <transition-group>
设置 name 特性时,例如name为fade,则 v-move 在使用时,需要替换为 fade-move。
注意:当移除一个列表元素时,需要将移除的元素脱离文档流,否则,要溢出的元素在移除过渡中一直处于文档流中,会影响到后面元素的move过渡效果。
内部的实现:Vue 使用了一个叫 FLIP 简单的动画队列,使用 transforms 将元素从之前的位置平滑过渡新的位置。
需要注意的是使用 FLIP 过渡的元素不能设置为 display: inline 。作为替代方案,可以设置为 display: inline-block 或者放置于 flex 中。
<template>
<div class="demo">
<button @click="handleAdd">添加</button>
<button @click="handleRemove">移除</button>
<button @click="handleShuffle">洗牌</button>
<br />
<transition-group tag="ul">
<li
v-for="item in lists"
:key="item"
>{
{
item }}</li>
</transition-group>
</div>
</template>
<script>
export default {
data () {
return {
lists: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
nextNum: 11,
}
},
methods: {
handleAdd () {
const randomIndex = Math.floor( Math.random() * this.lists.length );
this.lists.splice(randomIndex, 0, this.nextNum ++);
},
handleRemove () {
const randomIndex = Math.floor( Math.random() * this.lists.length );
this.lists.splice(randomIndex, 1);
},
handleShuffle () {
this.lists.sort(() => Math.random() - 0.5);
},
},
}
</script>
<style scoped>
button {
margin-bottom: 10px;
margin-right: 10px;
}
ul,li {
padding: 0;
margin: 0;
}
li {
list-style: none;
display: inline-block;
margin-right: 10px;
}
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateY(30px);
}
.v-enter-active,
.v-leave-active {
transition: all .3s;
}
.v-leave,
.v-enter-to {
opacity: 1;
transform: translateY(0px);
}
.v-move {
transition: transform .3s;
}
</style>
3.列表的交错过渡
如果要给列表中的元素,应用更丰富的过渡效果,可以配合JavaScript钩子。
<template>
<div class="demo">
<input type="text" v-model="query">
<transition-group tag="ul"
@before-enter="beforeEnter"
@enter="enter" @leave="leave">
<li v-for="item in computedLists"
:key="item.name">
{
{
item.name }}
</li>
</transition-group>
</div>
</template>
<script>
export default {
data () {
return {
query: '',
lists: [
{
name: 'shanshan'},
{
name: 'jicheng'},
{
name: 'chensitong'},
{
name: 'dengxuming'},
]
}
},
computed: {
computedLists () {
return this.lists.filter(item => item.name.includes(this.query));//筛选包含输入字符的
},
},
methods: {
beforeEnter (el) {
el.style.opacity = 0;
el.style.height = 0;
},
enter (el, done) {
Velocity(el, {
opacity: 1, height: '24px' }, {
duration: 300, complete: done })
},
leave (el, done) {
Velocity(el, {
opacity: 0, height: '0px' }, {
duration: 300, complete: done })
}
},
}
</script>
<style scoped>
li {
height: 24px;
}
</style>