如何给页面加入场和退场的动画
思路:利用 vuex 将路由保存在队列中,前进的时候压入队列,后退的时候移出队列
用到的技术:Vue Vuex VueRouter Van
1. 监听路由的beforeEach
事件
// src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
routes: [
// 这里面自己写路由
]
})
router.beforeEach((to, from, next) => {
// 这个方法在后面会写
store.dispatch('setRouter', { to, from }).then(() => next())
})
export default router
2. 在setRouter
中处理入场和退场的操作,这个是vuex
中的action
方法
// src/store/index.js
import Vue from Vue;
import Vuex from 'vuex'
Vue.use(vuex)
const appModule = new Vuex.Store({
state: {
name: 'van-slide-left', // 动画名称
history: [] // 保存的路由队列
},
mutations: {
historyPush (state, route) {
state.history.push(route)
state.name = 'van-slide-left' // 入场的动画名称,这里是用的 vant-ui 这个框架的
},
historyPop (state, route) {
state.history = state.history.filter((_) => _.fullPath !== route.fullPath)
state.name = 'van-slide-right' // 出场的动画名称,这里是用的 vant-ui 这个框架的
}
},
actions: {
setRouter ({ commit, state }, payload) {
// 判断目标路由是否在 history 中
const fullPaths = state.history.map((_) => _.fullPath)
if (!fullPaths.includes(payload.to.fullPath)) {
// 不存在
commit('historyPush', payload.from)
} else {
// 存在
commit('historyPop', payload.to)
}
}
},
getters: {
getAnimationName (name) {
return state.name
}
}
})
export default appModule
3. 路由监听和路由的动画已经确认,使用动画
// src/main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import state from './state'
new Vue({
router,
state,
render: h => h(App)
}).$mount('#app')
4. App.vue
中使用transition
加上动画效果
<template>
<div id="app">
<transition :name="getAnimationName">
<keep-alive><router-view /></keep-alive>
</transition>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['getAnimationName'])
}
}
</script>
5. ⚠️注意,以上动画可能导致页面抖动,可以在App.vue
中加上如下样式
.van-slide-left-leave-to,
.van-slide-right-leave-to {
display: none;
}