单元素/单组件动画用 transition
可以用在单元素/单组件的外层,然后结合vue定义好的类名,来控制动画效果。
类名:
.v-enter-from - - -动画入场开始状态
.v-enter-to - - -动画入场结束状态
.v-enter-active - - -动画入场过程状态
.v-leave-from - - -动画出场开始状态
.v-leave-to - - -动画出场结束状态
.v-leave-active - - -动画出场过程状态
入场:从无到到有
出场:从有到无
类名默认是 “v” 开头,如果想要自定义类名,可以设置 transition 的 “name” 属性
eg:
默认:
<transition>
<div>今天也是元气满满的一天呀!!!</div>
</transition>
自定义名称:
<transition name="good">
<div>今天也是元气满满的一天呀!!!</div>
</transition>
该类名对应为:
.good-enter-from - - -动画入场开始状态
.good-enter-to - - -动画入场结束状态
.good-enter-active - - -动画入场过程状态
.good-leave-from - - -动画出场开始状态
.good-leave-to - - -动画出场结束状态
.good-leave-active - - -动画出场过程状态
如果想要页面首次出现时也有动画效果,可以用- - - appear
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单元组的入场出场封装</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<style>
.v-enter-from {
opacity: 0
}
/* 可省略
.v-enter-to {
opacity: 1
} */
.v-enter-active, .v-leave-active {
transition: opacity 3s ease-out
}
/* 可省略
.v-leave-from {
opacity: 1;
} */
.v-leave-to {
opacity: 0;
}
.day {
padding: 20px;
color: palevioletred;
}
</style>
<script>
const app = Vue.createApp({
data() {
return {
show: true
}
},
methods: {
handleClick() {
this.show = !this.show
}
},
template: `
<div>
<transition appear>
<div v-if="show" class="day">今天也是元气满满的一天呀!!!</div>
</transition>
<button @click="handleClick">点击显示/隐藏</button>
</div>
`
})
const vm = app.mount('#root')
</script>
</html>
页面效果:
多个单元素的切换
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多个单元素/单组件切换</title>
<script src="https://unpkg.com/vue@next"></script>
<style>
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 3s ease-in;
}
.v-enter-to,
.v-leave-from {
opacity: 1;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show
}
},
template: `
<div>
<transition>
<div v-if="show">你好,我是波吉</div>
<div v-else>你好,我是卡克</div>
</transition>
<button @click="handleClick">点击切换</button>
</div>
`
})
const vm = app.mount('#root')
</script>
</html>
页面效果:
多个单组件的切换
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多个单组件之间切换</title>
<script src="https://unpkg.com/vue@next"></script>
<style>
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s ease-in;
}
.v-enter-to,
.v-leave-from {
opacity: 1;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
<script>
const componentA = {
template: '<div>你好,我是波吉</div>'
}
const componentB = {
template: '<div>你好,我是卡克</div>'
}
const app = Vue.createApp({
data() {
return {
component: 'component-a'
}
},
methods: {
handleClick() {
if(this.component === 'component-a') {
this.component = 'component-b'
} else {
this.component = 'component-a'
}
}
},
components: {
'component-a': componentA,
'component-b': componentB
},
template: `
<transition mode="out-in" appear>
<component :is="component" />
</transition>
<button @click="handleClick">点击切换</button>
`
})
const vm = app.mount('#root')
</script>
</html>
页面效果:
控制入场出场顺序:mode
默认情况下,入场出场是同时进行的,可以使用 “mode” 设置入场、出场顺序
mode=“out-in” - - - 先出场,再入场
mode=“in-out”- - -先入场,再出场
第一次进入也有动画:appear
多个元素动画用transition-group
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>列表动画</title>
<script src="https://unpkg.com/vue@next"></script>
<style>
.list-item {
display: inline-block;
width: 60px;
height: 60px;
line-height: 60px;
margin-right: 10px;
text-align: center;
border: 1px solid green;
background-color: #eee;
border-radius: 30px;
}
.v-enter-from, .v-leave-to {
opacity: 0;
transform: translateY(30px);
}
.v-enter-active, .v-leave-active {
transition: all .5s ease;
}
.v-enter-to, .v-leave-from {
opacity: 1;
transform: translateY(0);
}
.v-move {
transition: all .5s ease;
}
.v-leave-active {
position: absolute;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
<script>
/* const app = Vue.createApp({
data() {
return {
list: [1, 2, 3]
}
},
methods: {
handleClickAdd() {
this.list.unshift(this.list.length + 1)
},
handleBClickRemove() {
this.list.shift(this.list.length)
}
},
template: `
<div>
<transition-group>
<span v-for="(item, index) in list" :key="index" class="list-item">烦恼{{item}}</span>
</transition-group>
<button @click="handleClickAdd">点击增加</button>
<button @click="handleBClickRemove">点击减少</button>
</div>
`
}) */
// 列表动画的实现
const app = Vue.createApp({
data() {
return { list: [1, 2, 3] }
},
methods: {
handleClickAdd() {
this.list.unshift(this.list.length + 1)
},
handleBClickRemove() {
this.list.shift(this.list.length)
}
},
template: `
<div>
<transition-group>
<span class="list-item" v-for="item in list" :key="item">烦恼{{item}}</span>
</transition-group>
<button @click="handleClickAdd">增加</button>
<button @click="handleBClickRemove">减少</button>
</div>
`
});
const vm = app.mount('#root')
</script>
</html>
页面效果:
注意 v-for循环 不要使用 index 作为key值
使用index作为键值的话,删除添加的动画效果都会是最后面的一个元素,前面真正添加/删除的元素没有该有的动画效果
eg:
注意元素入场/出场时,其他元素也缓速移动位置:.v-move
出场其他元素缓动还要加上:
.v-leave-active {
position: absolute;
}