一、基础使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
/* 动画 */
@keyframes rightToLeft {
0% {
transform: translateX(100px);
}
50% {
transform: translateX(50px);
}
100% {
transform: translateX(0);
}
}
.animation {
animation: rightToLeft 3s;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
animate:{
animation: false
}
};
},
methods:{
handleClick(){
this.animate.animation = !this.animate.animation;
}
},
template: `
<div :class='animate'>666666</div>
<button @click=handleClick>动起来</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
/* 过渡 */
.transition {
transition: background-color 3s ease;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
transition: {
transition: true,
blue: true,
green: false
}
};
},
methods: {
handleClick() {
this.transition.blue = !this.transition.blue;
this.transition.green = !this.transition.green;
}
},
template: `
<div :class='transition'>666666</div>
<button @click=handleClick>变色</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
/* 过渡 */
.transition {
transition: background-color 3s ease;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
styleObj: {
backgroundColor: 'blue'
}
};
},
methods: {
handleClick() {
if (this.styleObj.backgroundColor === 'blue') {
this.styleObj.backgroundColor = 'green';
} else {
this.styleObj.backgroundColor = 'blue'
}
}
},
template: `
<div class='transition' :style='styleObj'>666666</div>
<button @click=handleClick>变色</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
二、使用 transition 标签实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
/* 过渡 */
/* 入场 */
.v-enter-from {
opacity: 0;
}
.v-enter-active {
transition: opacity 3s ease-out;
}
.v-enter-to {
opacity: 1;
}
/* 出场 */
.v-leave-from {
opacity: 1;
}
.v-leave-active {
transition: opacity 3s ease-out;
}
.v-leave-to {
opacity: 0;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
// 单元素,单组件的入场出场动画
const app = Vue.createApp({
data() {
return {
show: false
};
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<transition>
<div v-if='show'>666666</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
/* 动画 */
@keyframes shake {
0% {
transform: translateX(100px)
}
50% {
transform: translateX(50px)
}
100% {
transform: translateX(0)
}
}
/*
transition 设置了 name 属性后,这里的
v-leave-active 需要修改为 my-leave-active
*/
.my-leave-active {
animation: shake .5s;
}
.my-enter-active {
animation: shake .5s;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
show: false
};
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<transition name='my'>
<div v-if='show'>666666</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
三、自定义过渡 class 类名
- 我们可以通过以下 attribute 来自定义过渡类名:
enter-from-class
enter-active-class
enter-to-class
leave-from-class
leave-active-class
leave-to-class
- 他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css. 结合使用十分有用。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
show: false
};
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<transition
enter-active-class="animate__animated animate__bounceInRight"
leave-active-class="animate__animated animate__bounceOutRight"
>
<div v-show='show'>666666</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
四、动画和过渡一起进行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<style>
@keyframes shake {
0% {
transform: translateX(50px)
}
50% {
transform: translateX(25px)
}
100% {
transform: translateX(0)
}
}
.v-enter-to {
color: red;
}
.v-leave-to {
color: red;
}
.v-enter-active {
animation: shake 10s;
transition: color 3s ease-in;
}
.v-leave-active {
animation: shake 10s;
transition: all 3s ease-in;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
show: false
};
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<transition type="transition">
<div v-show='show'>666666</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<style>
@keyframes shake {
0% {
transform: translateX(50px)
}
50% {
transform: translateX(25px)
}
100% {
transform: translateX(0)
}
}
.v-enter-to {
color: red;
}
.v-leave-to {
color: red;
}
.v-enter-active {
animation: shake 3s;
transition: color 1s ease-in;
}
.v-leave-active {
animation: shake 3s;
transition: all 1s ease-in;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
show: false
};
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<transition :duration="1000">
<div v-show='show'>666666</div>
</transition>
<transition :duration="{ enter:500, leave:1500 }">
<div v-show='show'>666666</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
五、使用 JavaScript 动画
- 可以在 attribute 中声明 JavaScript 钩子
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
<!-- 关闭css动画 -->
:css="false"
>
</transition>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
show: false
};
},
methods: {
handleClick() {
this.show = !this.show;
},
handleBeforeEnter(el) {
el.style.color = "red";
},
handleEnter(el, done) {
const animation = setInterval(() => {
const color = el.style.color;
if (color === 'red') {
el.style.color = 'green';
} else {
el.style.color = 'red';
}
}, 500)
setTimeout(() => {
clearInterval(animation);
done();
}, 3000)
},
handleAfterEnter(el) {
el.style.color = "black";
alert(666);
},
handleBeforeLeave(el) {
el.style.backgroundColor = "red";
},
handleLeave(el, done) {
const animation = setInterval(() => {
const backgroundColor = el.style.backgroundColor;
if (backgroundColor === 'red') {
el.style.backgroundColor = 'green';
} else {
el.style.backgroundColor = 'red';
}
}, 500)
setTimeout(() => {
clearInterval(animation);
done();
}, 3000)
},
handleAfterLeave(el) {
el.style.backgroundColor = 'white';
alert(777);
},
},
template: `
<transition
:css="false"
@before-enter="handleBeforeEnter"
@enter="handleEnter"
@after-enter="handleAfterEnter"
@before-leave="handleBeforeLeave"
@leave="handleLeave"
@after-leave="handleAfterLeave"
>
<div v-show='show'>666666</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
六、多个单元素标签的切换
- 可以设置 mode 改变过度模式,默认进入和离开是同时生效的。
in-out
: 新元素先进行过渡,完成之后当前元素过渡离开。out-in
: 当前元素先进行过渡,完成之后新元素过渡进入。- 可以通过
appear
attribute 设置节点在初始渲染的过渡。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
.v-leave-to {
opacity: 0;
}
.v-enter-from {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s ease-in;
}
.v-leave-from,
.v-enter-to {
opacity: 1;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
// 多个单元素标签之间的切换
const app = Vue.createApp({
data() {
return {
show: true
};
},
methods: {
handleClick() {
this.show = !this.show;
},
},
template: `
<transition mode='out-in' appear>
<div v-if='show'>enter</div>
<div v-else='show'>leave</div>
</transition>
<button @click=handleClick>切换</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>
七、多个组件之间的过渡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
<style>
.v-leave-to {
opacity: 0;
}
.v-enter-from {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s ease-in;
}
.v-leave-from,
.v-enter-to {
opacity: 1;
}
</style>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
// 多个单组件之间的切换
const ComponentA = {
template: '<div>hello world</div>'
}
const ComponentB = {
template: '<div>bye world</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>
</body>
</html>
八、状态动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>使用 Vue 实现 CSS 过渡与动画效果</title>
</head>
<body>
<div id="root">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
// 状态动画
const ComponentA = {
template: '<div>hello world</div>'
}
const ComponentB = {
template: '<div>bye world</div>'
}
const app = Vue.createApp({
data() {
return {
num: 1,
maxNum: 10
};
},
methods: {
handleClick() {
if (this.num < this.maxNum) {
const animation = setInterval(() => {
this.num++;
if (this.num === this.maxNum) {
clearInterval(animation);
}
}, 100);
}
},
},
template: `
<div>{{num}}</div>
<button @click=handleClick>增加</button>
`
});
const vm = app.mount('#root');
</script>
</body>
</html>