本篇代码示例:github

前提:不关注移动端浏览器的前进事件

涵盖功能:
 1,管理路由的历史记录

 2,切页动画的实现

 3,处理流程类页面的回退事件

描述:

   流程类页面的回退事件的解释:
 以注册页面举例, 为了拉长整个流程,把输入项分开。以下是整个流程(懒得画图,大家将就看)

 1.首页 - 点击首页注册按钮可进入注册输入页

 2.注册输入页 - 输入姓名

 3.注册输入页 - 输入电话

 4.提交注册页 - 点击提交按钮,获取注册状态(成功或者失败),如果成功,则跳转到指定页面(假定是产品页)

 5.产品页

 以上是一个简单的注册的流程,现在写一下业务场景和需求

 1,注册未完成时

   注册未完成时,页面可能处于 1,2,3,4 这几个页面,此时,点击返回(无论是页面本身自带的返回,还是浏览器或者设备-[如安卓]的返回键触发的返回) 均可回到上一页

 2.注册完成时

  指注册成功并已经进入 5 页面 ,此时,点击返回(浏览器或者设备-[如安卓]的返回键触发的返回),回到 4 页面之后,要求直接跳回 1 页面

准备工作

 1.切页动画的实现

  切页动画使用vue自带的 过渡效果 transition 实现, 这个是附带的,这里不讲,大家自己看代码,代码如下

<template>
<div class="wapper">
<transition :name="transition">
<router-view class="child-view"></router-view>
</transition>
</div>
</template> <script> export default {
name: 'tableDemo',
data () {
return {
transition: 'slide-left'
}
},
methods: {
doSomething (e) {
this.$router.delLastRouter() // 页面回退时,路由做对应的处理
}
},
created () {
window.addEventListener('popstate', this.doSomething, false) // 监听回退事件
},
beforeRouteUpdate (to, from, next) {
window.document.title = to.meta.title
let isBack = this.$router.isBack
if (isBack) {
this.transition = 'slide-right'
next()
} else {
// 进入页面之前判断是否是进入流程页
if (from.meta.isStartPage) {
this.$router.setProcessStatus(to.meta.group, false)
}
this.transition = 'slide-left'
next()
}
}
}
</script> <style lang="scss">
.wapper { position: relative; width: 100%; height: 100%;}
.child-view { position: absolute; width:100%; height: 100%;}
.slide-left-leave { -webkit-transform: translate(0, 0); transform: translate(0, 0);}
.slide-left-leave-active { transition: all .4s cubic-bezier(.55,0,.1,1);}
.slide-left-leave-to { -webkit-transform: translate(100%, 0); transform: translate(100%, 0);}
.slide-left-enter { -webkit-transform: translate(-100%, 0); transform: translate(-100%, 0);}
.slide-left-enter-active { transition: all .4s cubic-bezier(.55,0,.1,1);}
.slide-left-enter-to { -webkit-transform: translate(0, 0); transform: translate(0, 0);} .slide-right-leave { -webkit-transform: translate(0, 0); transform: translate(0, 0);}
.slide-right-leave-active { transition: all .4s cubic-bezier(.55,0,.1,1);}
.slide-right-leave-to { -webkit-transform: translate(-100%, 0); transform: translate(-100%, 0);}
.slide-right-enter { -webkit-transform: translate(100%, 0); transform: translate(100%, 0);}
.slide-right-enter-active { transition: all .4s cubic-bezier(.55,0,.1,1);}
.slide-right-enter-to { -webkit-transform: translate(0, 0); transform: translate(0, 0);} </style>

 2.路由的管理

  1. 为vue-router设置一些状态

Router.prototype.routerArray = []; // 存储过往的路由信息
Router.prototype.processArray = []; // 存储流程页的状态
Router.prototype.isBack = false; // 是否是返回,动画使用

  2. 使用 beforeRouteUpdate 来检查路由的变化 这里要注意的事情是 beforeRouteUpdate 只针对子路由生效  ,所以这段代码放在父路由指向的页面中

  在这个页面,我们通过 this.$router.isBack 来区分页面是前进还是后退,并调整对应的动画效果。

beforeRouteUpdate (to, from, next) {
window.document.title = to.meta.title
let isBack = this.$router.isBack
if (isBack) {
this.transition = 'slide-right'
next()
} else {
// 进入页面之前判断是否是进入流程页
if (from.meta.isStartPage) {
this.$router.setProcessStatus(to.meta.group, false)
}
this.transition = 'slide-left'
next()
}
}

  3. 重写路由的push方法  在push方法中 如果push指向的页面已经存在于历史记录中,则当做返回处理, 前进则为 历史记录添加一条数据

// 修改 Router本身的push, 跳转之前做一些判断
let lPush = Router.prototype.push;
Router.prototype.push = function (location, onComplete, onAbort) {
let lGoCount = this.havRouterHistory(location)
if (lGoCount < 0) {
this.isBack = true
this.go(lGoCount);
} else {
this.isBack = false
this.routerArray.push(this.history.current)
lPush.call(this, location, onComplete, onAbort)
}
};

  4.重写路由的go方法

// 重写 Router 本身的 go, 回退的同时要清空记录中的数据
let lGo = Router.prototype.go
Router.prototype.go = function (n) {
if (n > 0) {
lGo.call(this, n);
return;
}
let lLen = 0 - n;
lLen = this.routerArray.length > lLen ? lLen : this.routerArray.length;
let lStart = this.routerArray.length - lLen;
this.routerArray.splice(lStart, lLen);
lGo.call(this, n);
};

  5.判断 push 时 指向的页面是否存在于历史记录中

// 判断历史记录中是否存在将要跳转的路由,如果有,执行回退操作
Router.prototype.havRouterHistory = function (location) {
// debugger
let lPath = location.path;
let lName = location.name;
let lLen = this.routerArray.length;
for (let i = 0; i < lLen; i++) {
if (this.routerArray[i].path === lPath || this.routerArray[i].name === lName ) {
return i - lLen; // 存在则返回应该回退的步数,注意回退的步数是负值
}
}
return 1 // 如果存在则必然小于0,所以这里写返回1代表不存在没有问题
};

  6.浏览器或者设备物理键触发回退

  在父路由页面设置全局的事件监听,在触发事件的时候处理路由

methods: {
doSomething (e) {
this.$router.delLastRouter() // 页面回退时,路由做对应的处理
}
},
created () {
window.addEventListener('popstate', this.doSomething, false) // 监听回退事件
},
// 浏览器回退时,清除最后一条路由数据  这串代码在 路由配置文件 中
Router.prototype.delLastRouter = function () {
this.routerArray.pop()
}

  7. 路由本身的回退事件   无需对路由的back事件做处理,因为vue-router本身的back 调用的  go(-1) go函数我们已经重写过了

  8.根据流程相关页面,对路由做相对应的配置

  isStartPage: true // 表示这是一个流程入口页,相当于上面的 页面1

  group  // group分组,代表了一组页面同属于一个流程中

/**
* 返回效果的Demo
*/
export default [
{
path: '/backDemoIndex',
name: 'backDemoIndex',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/index')), 'BackDemo/index'),
meta: { title: '入口选择页面' }
},
{
path: '/backAPage',
name: 'backAPage',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/aPage')), 'BackDemo/aPage'),
meta: { title: '操作起始页面aaaaa', isStartPage: true }
},
{
path: '/backAPageA',
name: 'backAPageA',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/aPagea')), 'BackDemo/aPagea'),
meta: { title: '操作起始页面bbb', isStartPage: true }
},
{
path: '/backAPageB',
name: 'backAPageB',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/aPageb')), 'BackDemo/aPageb'),
meta: { title: '操作起始页面CCC', isStartPage: true }
},
{
path: '/backBPage',
name: 'backBPage',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/bPage')), 'BackDemo/bPage'),
meta: { title: '第一个输入页面', group: 'backDemo' }
},
{
path: '/backCPage',
name: 'backCPage',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/cPage')), 'BackDemo/cPage'),
meta: { title: '第二个输入页面', group: 'backDemo' }
},
{
path: '/backDPage',
name: 'backDPage',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/dPage')), 'BackDemo/dPage'),
meta: { title: '结果页面', group: 'backDemo' }
},
{
path: '/other',
name: 'other',
component: r => require.ensure([], () => r(require('../../Page/BackDemo/other')), 'BackDemo/other'),
meta: { title: '结果页面' }
}
]

  9.在流程起始页进入流程页是,修改流程的状态

  this.$router.setProcessStatus( ‘backDemo’, false)  //  groupName 流程分组名称   status  流程状态 true为已经完成  false 为 未完成

// 修改一个流程的状态
Router.prototype.setProcessStatus = function (groupName, status) {
this.processArray[groupName] = status
};

  10.在每个流程页 检查流程的完成情况

  this.$router.onPageLoad()

// 找到最近的入口页面
Router.prototype.findInsterPage = function () {
let lLen = this.routerArray.length;
for (let i = lLen - 1; i >= 0; i--) {
if (this.routerArray[i].meta.isStartPage) {
return i - lLen
}
}
return 1; // 如果存在则必然小于0,所以这里写返回1代表不存在没有问题
} // 如果进入一个流程页,并且该页面的状态已经是完成,则应该回退到最近的流程入口页面,或者 跳转到指定的页面
Router.prototype.onPageLoad = function (query) {
// debugger
if (this.history.current.meta.group) {
let lNowRouter = this.history.current.meta.group
let lStatus = this.processArray[lNowRouter]
if (lStatus) {
let lRes = this.findInsterPage()
if (lRes < 0) {
this.go(lRes)
}
}
}
};

  11. 在流程结果处理页面,更改流程状态为完成  this.$router.setProcessStatus( ‘backDemo’, true)

  

基于vue-router的移动端网页的路由管理的更多相关文章

  1. 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框

    vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...

  2. 基于VUE.JS的移动端框架Mint UI

    Mint UI GitHub:github.com/ElemeFE/mint 项目主页:mint-ui.github.io/# Demo:elemefe.github.io/mint- 文档:mint ...

  3. 在微信框架模块中,基于Vue&Element前端的事件和内容的管理

    在微信后台管理中,我们需要定义好菜单对应的事件管理,因为微信通过菜单触发相关的事件,因此菜单事件的响应关系,我们如果处理好,就能构建出我们的微信应用入口了.通过入口,我们可以响应用户菜单的事件,如响应 ...

  4. 基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多

    通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无 ...

  5. Vue 爬坑之路(十一)—— 基于 Nuxt.js 实现服务端渲染(SSR)

    直接使用 Vue 构建前端单页面应用,页面源码时只有简单的几行 html,这并不利于网站的 SEO,这时候就需要服务端渲染 2016 年 10 月 25 日,zeit.co 背后的团队对外发布了一个 ...

  6. 优秀的基于VUE移动端UI框架合集

    1. vonic 一个基于 vue.js 和 ionic 样式的 UI 框架,用于快速构建移动端单页应用,很简约,是我喜欢的风格 star 2.3k 中文文档 在线预览 2.vux 基于WeUI和Vu ...

  7. 前端基于vue,后台采用springboot+shiro的方式搭建的一个移动端商品展示平台

    基于vue实现的移动端商品展示页,可以web-view的方式嵌入到小程序中,布局简约.大气,减少初学者或开发者不必要的工作量.后台维护采用的springboot+shiro的方式,为广大爱好者提供展示 ...

  8. [Vue 牛刀小试]:第十二章 - 使用 Vue Router 实现 Vue 中的前端路由控制

    一.前言 前端路由是什么?如果你之前从事的是后端的工作,或者虽然有接触前端,但是并没有使用到单页面应用的话,这个概念对你来说还是会很陌生的.那么,为什么会在单页面应用中存在这么一个概念,以及,前端路由 ...

  9. 新建一个基于vue.js+Mint UI的项目

    上篇文章里面讲到如何新建一个基于vue,js的项目(详细文章请戳用Vue创建一个新的项目). 该项目如果需要组件等都需要自己去写,今天就学习一下如何新建一个基于vue.js+Mint UI的项目,直接 ...

随机推荐

  1. 【已解决】iOS11使用MJRefresh上拉加载结束tableView闪动、跳动的问题

    更新提示: [2018年11月20日更新] 经过放置在项目中运行发现,如果在快速滚动tableview的时候会在下面这行代码中崩溃(慢慢的滚动是没关系的-): CGFloat cellHeight = ...

  2. spring boot 是如何启动 tomcat

    Spring boot 的启动类启动后,tomcat 容器.Spring mvc .spring 事务等等第三方依赖也已经自动启动,那么spring boot 是如何启动的第三方依赖? 以spring ...

  3. Java基础 -2.3

    浮点数类型 所有的数据类型进行自动转型的时候都是由小类型到大类型进行自动转换处理.默认的类型为double,但是也可以定义位数相对较少的float变量 ,此时从赋值的时候就必须采用强制类型转换 pub ...

  4. spring boot ApplicationRunner使用

    spring boot ApplicationRunner使用 它的使用比较简单,实现ApplicationRunner的run方法 package com.hikvision.pbg.jc.conf ...

  5. System.arraycopy方法解释

    数组拷贝 public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int lengt ...

  6. ARM CORTEX-M3 内核架构理解归纳

    ARM CORTEX-M3 内核架构理解归纳 来源:网络 个人觉得对CM3架构归纳的非常不错,因此转载 基于<ARM-CORTEX M3 权威指南>做学习总结: 在我看来,Cotex-M3 ...

  7. [运维] 如何在 Linux 上安装 Nginx 服务器(一)

    原因 因为小程序对素材的大小是由要求的, 所以为了简化小程序上的内存要求, 在Linux上安装nginx来作为静态资源服务器, 这篇为第一篇, 主要介绍怎么在Linux上安装nginx, 下一篇将会介 ...

  8. Springboot + redis + 注解 + 拦截器来实现接口幂等性校验

    Springboot + redis + 注解 + 拦截器来实现接口幂等性校验   1. SpringBoot 整合篇 2. 手写一套迷你版HTTP服务器 3. 记住:永远不要在MySQL中使用UTF ...

  9. Python 基础之linux基础相关

    一: python3.6.x在Ubuntu16.04下安装过程 #(1)保证网络正常连接 sudo add-apt-repository ppa:jonathonf/python-3.6  (如果超时 ...

  10. C#中as用法---转载

    转载 jiang13824690 发布于2018-07-24 11:19:00 阅读数 3302 收藏 展开 在程序中,进行类型转换时常见的事,C#支持基本的强制类型转换方法,例如  Object o ...