需求
- 页面切换的时候有页面切换动效
- 详情页右滑可以返回到前一个页面
- 前一个页面需要做页面缓存
思路
- 页面切换动效使用
transition
,需要区分前进还是后退。vue-router
没有提供该功能,自己写一个返回的方法,返回的时候调用该方法 - 右滑返回可以写一个自定义指令,需要右滑返回的页面添加该指令
- 做页面缓存使用
keep-alive
实现
- 修改
src/router/index.js
文件
import Vue from 'vue'
import VueRouter from 'vue-router'
// ...
// 这里定义一个goBack方法,通过该方法后退
VueRouter.prototype.goBack = function() {
this.isBack = true
if (this.history.current.query.goindex === 'true') {
this.push('/')
} else {
window.history.go(-1)
}
}
// push全局捕获异常
const routerPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return routerPush.call(this, location).catch(error => error)
}
Vue.use(VueRouter)
// ...
- 修改
src/App.vue
文件
<template>
<div id="app">
<transition :name="transitionName" :mode="transitionMode" :duration="300">
<keep-alive exclude="postReply">
<router-view />
</keep-alive>
</transition>
</div>
</template>
export default {
data() {
return {
transitionName: '',
transitionMode: ''
}
},
watch: {
$route(to, from) {
if (from.name !== undefined && from.name === to.name) {
this.transitionName = ''
this.transitionMode = ''
return false
}
// 监听路由变化时的状态为前进还是后退
const isBack = this.$router.isBack
this.$router.isBack = false
if (to.meta.index === 100) {
this.transitionName = 'slide-top'
// this.transitionMode = 'in-out'
} else if (from.meta.index === 100) {
this.transitionName = 'slide-bottom'
// this.transitionMode = 'in-out'
setTimeout(() => {
this.transitionName = ''
this.transitionMode = ''
}, 150)
} else {
if (isBack) {
this.transitionName = 'slide-right'
// this.transitionMode = 'in-out'
} else {
this.transitionName = 'slide-left'
// this.transitionMode = 'in-out'
}
}
}
}
}
@transformTime: .3s;
#app{
position: relative;
width: 100%;
height: 100%;
.router-view{
position: absolute;
}
.slide-right-enter-active,
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active,
.slide-top-enter-active,
.slide-top-leave-active,
.slide-bottom-enter-active,
.slide-bottom-leave-active{
will-change: transform;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
// 左右切换
.slide-left-enter-active{
animation: slideInLeft @transformTime forwards;
}
.slide-left-leave-active{
animation: slideOutLeft @transformTime forwards;
}
.slide-right-enter-active{
animation: slideInRight @transformTime forwards;
}
.slide-right-leave-active{
animation: slideOutRight @transformTime forwards;
}
// 上下切换
.slide-top-enter-active{
animation: slideInTop @transformTime forwards;
}
.slide-top-leave-active{
animation: slideOutTop @transformTime forwards;
}
.slide-bottom-enter-active{
animation: slideInBottom .03s forwards;
}
.slide-bottom-leave-active{
animation: slideOutBottom @transformTime forwards;
}
}
// 左右切换
@keyframes slideInLeft {
0%{transform: translate3d(100%, 0, 0);}
100%{transform: translate3d(0, 0, 0);}
}
@keyframes slideInRight {
0%{transform: translate3d(-100%, 0, 0);}
100%{transform: translate3d(0, 0, 0);}
}
@keyframes slideOutLeft {
0%{transform: translate3d(0, 0, 0);opacity: 1;}
100%{transform: translate3d(-100%, 0, 0);opacity: 0.4;}
}
@keyframes slideOutRight {
0%{transform: translate3d(0, 0, 0);opacity: 1;}
100%{transform: translate3d(100%, 0, 0);opacity: 0.4;}
}
// 上下切换
@keyframes slideInTop {
0%{transform: translate3d(0, 100%, 0);}
100%{transform: translate3d(0, 0, 0);}
}
@keyframes slideInBottom {
0%{transform: translate3d(0, -100%, 0);}
100%{transform: translate3d(0, 0, 0);}
}
@keyframes slideOutTop {
0%{transform: translate3d(0, 0, 0);opacity: 1;}
100%{transform: translate3d(0, -100%, 0);opacity: 0.4;}
}
@keyframes slideOutBottom {
0%{transform: translate3d(0, 0, 0);opacity: 1;}
100%{transform: translate3d(0, 100%, 0);opacity: 0.4;}
}
-
在
src/
目录下新建src/directives/
-
在
src/directives/
目录下新建scroll-back.js.js
文件
import Vue from 'vue'
import router from '../router'
Vue.directive('scroll-back', {
inserted: function(el, binding) {
const startPos = { x: 0, y: 0 }
const endPos = { x: 0, y: 0 }
el.addEventListener('touchstart', e => {
if (!e.touches.length) {
return
}
startPos.x = e.touches[0].pageX
startPos.y = e.touches[0].pageY
endPos.x = 0
endPos.y = 0
})
el.addEventListener('touchmove', e => {
if (!e.touches.length) {
return
}
endPos.x = e.touches[0].pageX
endPos.y = e.touches[0].pageY
})
el.addEventListener('touchend', e => {
// 位移小于100的不翻页
const offsetX = endPos.x - startPos.x
const offsetY = endPos.y - startPos.y
if (offsetX > 100 && offsetX > Math.abs(offsetY)) {
router.goBack()
}
})
}
})
- 修改
src/main.js
文件
// ...
// directives
import './directives/scroll-back.js'
// ...
- 修改详情页面,添加
v-scroll-back
<template>
<div v-scroll-back>
<!-- ... -->
</div>
</template>
发表评论