基于vue-router的移动端网页的路由管理
本篇代码示例: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的移动端网页的路由管理的更多相关文章
- 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框
vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...
- 基于VUE.JS的移动端框架Mint UI
Mint UI GitHub:github.com/ElemeFE/mint 项目主页:mint-ui.github.io/# Demo:elemefe.github.io/mint- 文档:mint ...
- 在微信框架模块中,基于Vue&Element前端的事件和内容的管理
在微信后台管理中,我们需要定义好菜单对应的事件管理,因为微信通过菜单触发相关的事件,因此菜单事件的响应关系,我们如果处理好,就能构建出我们的微信应用入口了.通过入口,我们可以响应用户菜单的事件,如响应 ...
- 基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多
通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无 ...
- Vue 爬坑之路(十一)—— 基于 Nuxt.js 实现服务端渲染(SSR)
直接使用 Vue 构建前端单页面应用,页面源码时只有简单的几行 html,这并不利于网站的 SEO,这时候就需要服务端渲染 2016 年 10 月 25 日,zeit.co 背后的团队对外发布了一个 ...
- 优秀的基于VUE移动端UI框架合集
1. vonic 一个基于 vue.js 和 ionic 样式的 UI 框架,用于快速构建移动端单页应用,很简约,是我喜欢的风格 star 2.3k 中文文档 在线预览 2.vux 基于WeUI和Vu ...
- 前端基于vue,后台采用springboot+shiro的方式搭建的一个移动端商品展示平台
基于vue实现的移动端商品展示页,可以web-view的方式嵌入到小程序中,布局简约.大气,减少初学者或开发者不必要的工作量.后台维护采用的springboot+shiro的方式,为广大爱好者提供展示 ...
- [Vue 牛刀小试]:第十二章 - 使用 Vue Router 实现 Vue 中的前端路由控制
一.前言 前端路由是什么?如果你之前从事的是后端的工作,或者虽然有接触前端,但是并没有使用到单页面应用的话,这个概念对你来说还是会很陌生的.那么,为什么会在单页面应用中存在这么一个概念,以及,前端路由 ...
- 新建一个基于vue.js+Mint UI的项目
上篇文章里面讲到如何新建一个基于vue,js的项目(详细文章请戳用Vue创建一个新的项目). 该项目如果需要组件等都需要自己去写,今天就学习一下如何新建一个基于vue.js+Mint UI的项目,直接 ...
随机推荐
- MyBatis 入门Demo
新建数据库my_db,新建表student_tb id为主键,不自动递增. 不必插入数据. 下载MyBatis https://github.com/mybatis/mybatis-3/release ...
- 一堂优秀学员吕智钊分享----HHR计划----直播课第二课
备注:本周四:创业者分享,下周四:投资人分享. 08年开始创业. 最重要的两条复盘思考: 大纲: ---坚持最低成本试错,最快速度学习---- 1,复盘1:创业早期如何快速学习 a,从竞争对手身上学习 ...
- Java中对于ClassLoader类加载器 嵌套了深度技术的价值
关于Java技术是一种不断兴起的编程语言,对于ClassLoader 是 Java 届最为神秘的技术之一,无数人被它伤透了脑筋,摸不清门道究竟在哪里.本文我带你彻底吃透 ClassLoader,让你甚 ...
- 并发编程之Event事件
Event事件 用来同步线程之间的状态. 举个例子: 你把一个任务丢到了子线程中,这个任务将异步执行.如何获取到这个任务的执行状态 解决方法: 如果是拿到执行结果 我们可以采用异步回调, 在这里我 ...
- js里用 toLocaleString 实现给数字加三位一逗号间隔(有无小数点都适用)
<input type="hidden" id="totalLandArea" value="<%-info.totalLandArea% ...
- MySql向SQLServer迁移常见问题
-- MySql与SQLServer update inner join语法区别-- MySql: UPDATE A LEFT JOIN B ON A.B_ID = B.B_ID SET A.A_NA ...
- Linux 允许root用户远程登陆
首先确保ssh服务已经安装: ps -e | grep ssh or service ssh start 如果没有安装则: apt-get install ssh 安装完之后 查看 /etc/ssh/ ...
- Go语言的map
map一般是以库的方式提供,在C++和C#和JAVA中都需要引用相应的库而Go语言不需要引入库,可以直接方便使用 定义:map是一堆键值对的未排序集合.无序 1.声明变量: map的声明基本上没有多余 ...
- mysql时出现:is not allowed to connect to this MySQL serverConnection closed by foreign host问题的解决
这个原因是因为索要链接的mysql数据库只允许其所在的服务器连接,需要在mysql服务器上设置一下允许的ip权限,如下: 1.连接mysql mysql -u root -p 1 如图: 2.授权 g ...
- 基于金山快盘的Git服务器、快盘+ Git GUI 实现代码版本管理
Git,这货堪称神器,用了它就再也不想用其他VCS了,就像上了高速就不想再走国道一样. Git的强大之处在于,你可以在局域网内的任何一个共享路径下创建仓库,而不需要运行任何服务.所有的操作都是 ...