Vue项目右滑返回

需求

  • 页面切换的时候有页面切换动效
  • 详情页右滑可以返回到前一个页面
  • 前一个页面需要做页面缓存

思路

  • 页面切换动效使用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>

创作不易,若本文对你有帮助,欢迎打赏支持作者!

 分享给好友: