Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:
在 CSS 过渡和动画中自动应用 class
可以配合使用第三方 CSS 动画库,如 Animate.css
在过渡钩子函数中使用 JavaScript 直接操作 DOM
可以配合使用第三方 JavaScript 动画库,如 Velocity.js
vue 动画 (`transition`)
使用命名形式
<transition name="t" mode="out-in" appear>
<h1 v-if="isShow">Hello World</h1>
</transition>
<style>
.t-enter-active {
animation: bounceInUp 1s ease-in-out;
}
.t-leave-active {
animation: bounceOutDown 1s ease-in-out;
}
</style>
使用加类名形式
<transition
enter-active-class="animate__animated animate__backInDown"
leave-active-class="animate__animated animate__backOutDown dir"
>
<h1 v-if="isShow">Hello LIUJUNJIE</h1>
</transition>
<style>
.dir {
animation-duration: reverse;
}
</style>
transition 组件的生命周期钩子
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
>
<h1 v-if="isShow">Hello World</h1>
</transition>
不添加 css 动画
<transition :css="false">
<h1 v-if="isShow">Hello World</h1>
</transition>
使用 animate.css
Animate.css | A cross-browser library of CSS animations.
npm install animate.css
可以使用添加类名的方式, 也可以使用动画形式如上列代码所示
使用 gsap
npm install gsap
<template>
<div>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
</div>
<transition @enter="enter" @leave="leave">
<h1 v-if="isShow">Hello World</h1>
</transition>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue"
import { gsap } from "gsap"
const isShow = ref(true)
const enter = (el: any, done: any) => {
console.log("enter")
gsap.from(el, {
scale: 0,
x: 200,
y: 200,
onComplete: done,
})
}
const leave = (el: any, done: any) => {
console.log("leave")
gsap.to(el, {
scale: 0,
x: 200,
y: 200,
onComplete: done,
})
}
</script>
el 为动画对象
done 为动画结束调用
其他属性可以详细查看 gsap
列表过度动画
列表过度动画使用
transition-group
其他属性与
transition
相同
<template>
<div>
<input type="text" v-model="text" />
<button @click="addItem">添加列表</button>
<button @click="removeItem">删除列表</button>
<ol>
<transition-group name="item">
<li class="item" v-for="(item, index) in list" :key="item">
{{ item }}
</li>
</transition-group>
</ol>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from "@vue/reactivity"
let list = reactive(["hello world", "吃饭", "睡觉", "打豆豆"])
const text = ref("")
const addItem = () => {
let index = Math.round(Math.random() * (list.length - 1))
list.splice(index, 0, text.value + list.length)
}
const removeItem = () => {
let index = Math.round(Math.random() * (list.length - 1))
list.splice(index, 1)
}
</script>
<style>
body {
padding: 50px;
}
* {
margin: 0;
padding: 0;
}
input {
font-size: 18px;
padding: 10px;
}
.item {
width: 100%;
background-color: #eeee;
padding: 10px;
border-radius: 10px;
margin-top: 30px;
}
.item-enter-active {
animation: lightSpeedInLeft 0.5s ease-in-out;
}
.item-leave-active {
animation: lightSpeedInLeft 0.3s ease-in-out reverse;
position: absolute;
z-index: 1111;
}
.item-move {
transition: 0.5s ease;
}
</style>
列表动画交替过度(解决一起添加或移除的生硬效果)
<template>
<div>
<input type="text" v-model="text" />
<transition-group
name="item"
tag="ol"
:css="false"
@enter="enter"
@leave="leave"
@beforeEnter="beforeEnter"
>
<li
class="item"
v-for="(item, index) in showNames"
:key="item"
:data-index="index"
>
{{ item }}
</li>
</transition-group>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, computed } from "@vue/reactivity"
import gsap from "gsap"
let list = reactive([
"hello world",
"吃饭",
"睡觉",
"打豆豆",
"aaaaa",
"刘俊杰",
"刘俊杰",
"刘小杰",
"刘俊杰",
"刘俊杰",
])
const text = ref("")
const showNames = computed(() => {
return list.filter((item) => item.indexOf(text.value) !== -1)
})
const beforeEnter = (el) => {
el.style.opacity = 0
el.style.height = 0
}
const enter = (el, done) => {
gsap.to(el, {
opacity: 1,
height: "1.5em",
delay: el.dataset.index * 0.1,
onComplete: done,
})
}
const leave = (el, done) => {
gsap.to(el, {
opacity: 0,
height: 0,
delay: el.dataset.index * 0.1,
onComplete: done,
})
}
</script>
<style>
body {
padding: 50px;
}
* {
margin: 0;
padding: 0;
}
input {
font-size: 18px;
padding: 10px;
}
.item {
width: 100%;
background-color: #eeee;
padding: 10px;
border-radius: 10px;
margin-top: 30px;
}
.item-enter-active {
animation: lightSpeedInLeft 0.5s ease-in-out;
}
.item-leave-active {
animation: lightSpeedInLeft 0.3s ease-in-out reverse;
position: absolute;
z-index: 1111;
}
.item-move {
transition: 0.5s ease;
}
</style>
文章转载自刘先生的闲语,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。