实现元素的滑入滑出效果,本篇介绍两种方式
- CSS动画实现
- CSS过渡实现
先看例子吧。
CSS动画
template模板中使用Vue组件:transition 。 css中使用动画:animation ,并配合样式类名xxx-enter-active 、xxx-leave-active 实现元素的滑入滑出效果。
Demo.vue,使用transition
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition>
<h2 v-show="isShow">虎虎生威</h2>
</transition>
</div>
</template>
<script>
export default {
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
}
.v-enter-active{
animation: slidein 1s linear;
}
.v-leave-active{
animation: slidein 1s linear reverse;
}
@keyframes slidein {
from{
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}
</style>
- 刷新时,没有动画,即初始渲染时没有过渡。
- 类名默认为
v-enter-active 或者v-leave-active 。
Demo.vue,使用transition,且自定义name
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition name="test">
<h2 v-show="isShow">虎虎生威</h2>
</transition>
</div>
</template>
<script>
export default {
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
}
.test-enter-active{
animation: slidein 1s linear;
}
.test-leave-active{
animation: slidein 1s linear reverse;
}
@keyframes slidein {
from{
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}
</style>
- 刷新时,没有动画,即初始渲染时没有过渡。
- 自定义了name,值为
test ,所以类名为test-enter-active 或者test-leave-active 。
Demo.vue,使用transition,且自定义name,且使用属性appear
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition name="test" appear>
<h2 v-show="isShow">虎虎生威</h2>
</transition>
</div>
</template>
<script>
export default {
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
}
.test-enter-active{
animation: slidein 1s linear;
}
.test-leave-active{
animation: slidein 1s linear reverse;
}
@keyframes slidein {
from{
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}
</style>
- 使用了属性
appear ,所以刷新时就有动画,即初始渲染时就有过渡。 - 自定义了name,值为
test ,所以类名为test-enter-active 或者test-leave-active 。
CSS过渡
template模板中使用Vue组件:transition 。 css中使用过渡:transition ,并配合以下样式类名实现元素的滑入滑出效果。
- 进入的样式
xxx-enter ,进入的起点xxx-enter-to ,进入的终点xxx-enter-active ,进入的过程 - 离开的样式
xxx-leave ,离开的起点xxx-leave-to ,离开的终点xxx-leave-active ,离开的过程
看具体例子。
使用xxx-enter、xxx-enter-to、xxx-leave、xxx-leave-to
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition name="test" appear>
<h2 v-show="isShow">虎虎生威</h2>
</transition>
</div>
</template>
<script>
export default {
name:"Demo",
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
transition: 1s linear;
}
.test-enter,.test-leave-to{
transform: translateX(-100%);
}
.test-enter-to,.test-leave{
transform: translateX(0);
}
</style>
使用xxx-enter、xxx-enter-to、xxx-leave、xxx-leave-to、xxx-enter-active、xxx-leave-active
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition name="test" appear>
<h2 v-show="isShow">虎虎生威</h2>
</transition>
</div>
</template>
<script>
export default {
name:"Demo",
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
}
.test-enter,.test-leave-to{
transform: translateX(-100%);
}
.test-enter-active,.test-leave-active{
transition: 1s linear;
}
.test-enter-to,.test-leave{
transform: translateX(0);
}
</style>
实现多个元素的滑入滑出
实现多个元素的滑入滑出效果,使用组件transition-group ,注意每个元素都要有个key 值,如下所示。
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition-group name="test" appear>
<h2 v-show="isShow" key="1">虎虎生威</h2>
<h2 v-show="isShow" key="2">一起向未来</h2>
</transition-group>
</div>
</template>
<script>
export default {
name:"Demo",
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
}
.test-enter,.test-leave-to{
transform: translateX(-100%);
}
.test-enter-active,.test-leave-active{
transition: transform 1s linear;
}
.test-enter-to,.test-leave{
transform: translateX(0);
}
</style>
集成第三方动画
使用npm中的animate.css。
- 安装animate.css
npm install --save animate.css
- 引入animate.css
import "animate.css";
- 使用animate.css
元素上添加name="animate__animated animate__bounce" ,且定义了 进入时的过渡状态:enter-active-class="animate__swing" 离开时的过渡状态:leave-active-class="animate__backOutUp"
<transition
appear
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__backOutUp"
>
<h2 v-show="isShow">虎虎生威</h2>
</transition>
最终的Demo.vue的内容如下所示,
<template>
<div class="demo">
<button @click="isShow=!isShow">显示/隐藏</button>
<transition
appear
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__backOutUp"
>
<h2 v-show="isShow">虎虎生威</h2>
</transition>
</div>
</template>
<script>
import "animate.css";
export default {
name:"Demo2",
data(){
return {
isShow:true
}
}
}
</script>
<style scoped>
h2{
background: orange;
}
</style>
todo-list案例
todo-list案例中,新增事项时,有滑入效果;删除事项时,有滑出效果,如下图所示。
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this;
},
}).$mount('#app')
<template>
<div id="app">
<Header :addTodo="addTodo"/>
<List :todos="todos"/>
<Footer :todos="todos"/>
</div>
</template>
<script>
import Header from './components/Header.vue';
import List from "./components/List.vue";
import Footer from "./components/Footer.vue";
export default {
name: 'App',
data(){
return {
todos:[]
}
},
methods:{
addTodo(todoObj){
this.todos.unshift(todoObj);
},
deleteTodo(id){
this.todos = this.todos.filter(todo => todo.id != id);
},
checkTodo(id){
this.todos.forEach(todo => {
if(todo.id == id) todo.done = !todo.done;
})
}
},
mounted(){
this.$bus.$on("deleteTodo",this.deleteTodo);
this.$bus.$on("checkTodo",this.checkTodo);
},
beforeDestroy(){
this.$bus.$off("deleteTodo");
this.$bus.$off("checkTodo");
},
components: {
Header,
List,
Footer
}
}
</script>
<style>
#app {
}
</style>
<template>
<div class="header">
<input type="text" placeholder="请输入" @keyup.enter="addTodoObj($event)">
</div>
</template>
<script>
import {nanoid} from "nanoid";
export default {
name:"Header",
props:["addTodo"],
methods:{
addTodoObj(e){
if(!e.target.value.trim()) return alert("输入不能为空!");
const todoObj = {
id:nanoid(),
title:e.target.value,
done:false
}
this.addTodo(todoObj);
e.target.value = "";
}
}
}
</script>
<style scoped>
.header{
padding: 5px;
}
.header input{
width: 300px;
height: 20px;
line-height: 20px;
}
</style>
<template>
<ul>
<transition-group>
<Item v-for="todo in todos" :key="todo.id" :todo="todo"/>
</transition-group>
</ul>
</template>
<script>
import Item from "./Item.vue";
export default {
name:"List",
props:["todos"],
components:{
Item
}
}
</script>
<style scoped>
ul{
margin: 0;
padding: 0;
}
.v-enter-active,.v-leave-active{
transition: transform .5s linear;
}
.v-enter,.v-leave-to{
transform: translateX(100%);
}
.v-leave,.v-enter-to{
transform: translate(0);
}
</style>
<template>
<li>
<label>
<input type="checkbox" :checked="todo.done" @change="checkTodo(todo.id)">
<span>{{todo.title}}</span>
</label>
<button @click="deleteTodo(todo.id)">删除</button>
</li>
</template>
<script>
export default {
name:"Item",
data(){
return {
done:false
}
},
props:["todo"],
methods:{
checkTodo(id){
this.$bus.$emit("checkTodo",id);
},
deleteTodo(id){
this.$bus.$emit("deleteTodo",id);
}
}
}
</script>
<style scoped>
li{
list-style: none;
width: 350px;
height: 25px;
padding: 5px;
border-radius: 3px;
display: flex;
align-content: center;
justify-content: space-between;
}
li:hover{
background: lightgray;
}
li:hover button{
display: inline-block;
}
li button{
display: none;
}
</style>
<template>
<div class="footer">
<span v-show="todos.length">已完成{{doneLen}} / 全部{{todos.length}}</span>
</div>
</template>
<script>
export default {
name:"Footer",
props:["todos"],
computed:{
doneLen(){
return this.todos.filter(todo => todo.done).length;
}
}
}
</script>
<style>
.footer{
padding: 5px;
}
</style>
|