Vue.js 動畫(三)
阿新 • • 發佈:2020-09-04
1. Vue 中的動畫
Vue
在插入、更新或者移除 DOM
時,提供多種不同方式的應用過渡效果。
包括以下工具:
- 使用過渡類名:使用
transition
元素包裹要設定動畫的元素 - 第三方 CSS 動畫庫:
animate.css
- 在過渡鉤子函式中使用
JavaScript
直接操作DOM
- 列表排序過渡:
transition-group
1.1 單元素過渡
Vue 提供了 transition 的封裝元件,在下列情形中,可以給任何元素和元件新增進入/離開過渡
- 條件渲染 (使用 v-if)
- 條件展示 (使用 v-show)
- 動態元件
- 元件根節點
1.1.1 過渡類名
在進入/離開的過渡中,會有 6 個 class 切換。
- v-enter:定義進入過渡的開始狀態。在元素被插入之前生效,在元素被插入之後的下一幀移除。
- v-enter-active:定義進入過渡生效時的狀態。在整個進入過渡的階段中應用,在元素被插入之前生效,在過渡/動畫完成之後移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函式。
- v-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入之後下一幀生效 (與此同時 v-enter 被移除),在過渡/動畫完成之後移除。
- v-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時立刻生效,下一幀被移除。
- v-leave-active:定義離開過渡生效時的狀態。在整個離開過渡的階段中應用,在離開過渡被觸發時立刻生效,在過渡/動畫完成之後移除。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函式。
- v-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發之後下一幀生效 (與此同時 v-leave 被刪除),在過渡/動畫完成之後移除。
示例:
給 h3
元素設定進入退出動畫:
<style> /* 自定義兩組樣式,來控制 transition 內部的元素實現動畫 */ /* v-enter 時間點,元素進入之前的其實狀態,此時還未正式進入 */ /* v-leave-to 時間點,動畫離開之後,離開的終止狀態,此時,元素動畫已結束 */ .v-enter, .v-levae-to { opacity: 0; /*透明度*/ transform: translateX(150px); /*元素從 150px 處飄過來,x 軸*/ } /* v-enter-active 入場動畫的時間段 */ /* v-levave-active 離場動畫的時間段 */ .v-enter-active, .v-levae-activue { transition: all 0.8s ease; } </style> <body> <div id="app"> <input type="button" value="按鈕" @click="flag=!flag"> <transition> <h3 v-if="flag">標題三</h3> </transition> </div> <script src="./lib/vue-2.4.0.js"></script> <script> var vm = new Vue({ el: '#app', data: { flag: false }, methods: {} }) </script> </body>
1.1.2 修改過渡類名字首給多個元素設定動畫
若有多個元素需要設定不同的動畫,如果使用同一種過渡類名,那麼動畫將是一致的,這時就需要修改過渡類名的字首 + transition
的 name
屬性來實現。
<style>
/* 自定義 v 字首 */
.my-enter,
.my-leave-to {
opacity: 0;
transform: translateY(70px); /*從上飛入*/
}
.my-enter-active,
.my-leave-active {
transition: all 0.8s ease;
}
</style>
<body>
<div id="app">
<input type="button" value="按鈕" @click="flag=!flag">
<transition>
<h3 v-if="flag">標題三</h3>
</transition>
<input type="button" value="按鈕2" @click="flag2=!flag2">
<transition name="my">
<h1 v-if="flag2">標題一</h3>
</transition>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
flag2: false
},
methods: {}
})
</script>
</body>
1.2 第三方 CSS 動畫庫 animate
1、匯入動畫類庫:
<link rel="stylesheet" type="text/css" href="./lib/animate.css">
2、定義 transition
及屬性:
<transition
enter-active-class="fadeInRight"
leave-active-class="fadeOutRight"
:duration="{ enter: 500, leave: 800 }">
<div class="animated" v-show="isshow">動畫哦</div>
</transition>
示例:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title Page</title>
<link rel="stylesheet" href="./lib/animate.css">
</head>
<body>
<div id="app">
<input type="button" value="按鈕" @click="flag=!flag">
<!-- 需求: 點選按鈕,讓 h3 顯示,再點選,讓 h3 隱藏 -->
<!-- <transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
<h3 v-if="flag">這是一個H3</h3>
</transition> -->
<!-- 使用 :duration="毫秒值" 來統一設定 入場 和 離場 時候的動畫時長 -->
<!-- <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="200">
<h3 v-if="flag" class="animated">這是一個H3</h3>
</transition> -->
<!-- 使用 :duration="{ enter: 200, leave: 400 }" 來分別設定 入場的時長 和 離場的時長 -->
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{ enter: 200, leave: 400 }">
<h3 v-if="flag" class="animated">標題三</h3>
</transition>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
},
methods: {}
})
</script>
</body>
</html>
參考文件:
1.3 JavaScript 鉤子函式
可以在屬性中宣告 JavaScript 鉤子,通過鉤子函式可以實現 半場動畫,所謂半場動畫,即只有進入之前或離開時的動畫,最常見的就是加入購物車的時候半場動畫。
<transition
<!-- 進入時的動畫 -->
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
<!-- 離開時的動畫 -->
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
JS 中呼叫:
// ...
methods: {
// --------
// 進入中
// --------
beforeEnter: function (el) {
// ...
},
// 當與 CSS 結合使用時
// 回撥函式 done 是可選的
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// 離開時
// --------
beforeLeave: function (el) {
// ...
},
// 當與 CSS 結合使用時
// 回撥函式 done 是可選的
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用於 v-show 中
leaveCancelled: function (el) {
// ...
}
}
示例:
利用 JavaScript 鉤子函式實現小球半場動畫,模擬加入購物車場景:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title Page</title>
<style>
.ball {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="按鈕" @click="flag=!flag">
<!-- 使用 transition 元素將小球包裹起來 -->
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
},
methods: {
beforeEnter(el) {
// 動畫入場之前,動畫尚未開始,用於設定元素開始動畫之前的起始樣式
// 設定小球開始動畫之前的起始位置
el.style.transform = "translate(0, 0)" // 起始座標
},
enter(el, done) {
el.offsetWidth // el.offsetWidth 會強制動畫重新整理
// 動畫開始之後的樣式,設定小球動畫之後的,結束狀態
el.style.transform = "translate(150px, 450px)" // 結束座標
el.style.transition = "all 1s ease"
done() // 起始就是 afterEnter 這個函式,也就是說:done 是 afterEnter 函式的引用
},
afterEnter(el) {
// 動畫完成後,隱藏小球,flag 初始值為 false,點選按鈕後為 true,!flag 即為 false
this.flag = !this.flag
}
}
})
</script>
</body>
</html>
Tips:當只用 JavaScript 過渡的時候,在 enter 和 leave 中必須使用 done 進行回撥。否則,它們將被同步呼叫,過渡會立即完成。
參考文章:
1.4 列表過渡
目前為止,關於過渡動畫我們已經瞭解了:
- 單個節點
- 同一時間渲染多個節點中的一個
若要渲染整個列表,使用 <transition-group>
元件,元件特點:
<transition-group>
會模組渲染為一個<span>
標籤,若想渲染為其他標籤,可以使用tag
屬性更換,如:tag="ul"
- 內部元素需要提供唯一的
key
屬性值 CSS
過渡類將會應用在內部元素中,而不是這個組/容器本身
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
<style>
li {
border: 1px dashed #999;
margin: 5px;
line-height: 35px;
padding-left: 5px;
font-size: 12px;
width: 100%;
}
li:hover {
background-color: hotpink;
transition: all 0.8s ease;
}
/* 過渡開始狀態,以及進入過渡的結束狀態 */
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateY(80px);
}
/* 進入過渡生效時的狀態,離開過渡生效時的狀態 */
.v-enter-active,
.v-leave-active {
transition: all 0.6s ease;
}
/* 下面的 .v-move 和 .v-leave-active 配合使用,能夠實現列表後續的元素,漸漸地漂上來的效果 */
.v-move {
transition: all 0.6s ease;
}
.v-leave-active {
position: absolute;
}
</style>
</head>
<body>
<div id="app">
<div class="col-md-8">
<div>
<label>
Id:
<input type="text" v-model="id">
</label>
<label>
Name:
<input type="text" v-model="name" @keyup.enter="add">
</label>
<input type="button" value="新增" @click="add">
</div>
<!-- 使用 transition-group 包裹要過渡的列表 -->
<!-- v-for 迴圈建立元素,設定動畫,且必須為每一個元素設定 :key 屬性 -->
<!-- appear 屬性,實現頁面展示時,入場時的結果 -->
<transition-group appear tag="ul">
<li v-for="(item, i) in list" :key="item.id" @click="del(i)">
{{ item.id }} --- {{ item.name }}
</li>
</transition-group>
</div>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
id: "",
name: "",
list: [
{ id: 1, name: '趙高' },
{ id: 2, name: '秦檜' },
{ id: 3, name: '嚴嵩' },
{ id: 4, name: '魏忠賢' }
]
},
methods: {
add() {
this.list.push({ id: this.id, name: this.name })
this.id = this.name = ''
},
del(i) {
this.list.splice(i, 1)
}
}
})
</script>
</body>
</html>
參考文章: