开发过程中发现 router 和 history 都不会提供后退事件标识, 并且很多时候我们并不想要后退历史, 而是后退页面层级.
并且在页面跳转过程中如果使用 go(-1),back() 这种事件还容易出现循环后退这种场景. 如: z->a->b->a; 在这样情况如果在 a,b 中使用后退, 将会按照浏览器历史后退, 那么 a/b 页面就会循环, 而我们在 a 页面实际是想要退回到 z.
同时 vue router 还是浏览器都没有地方判断是否为后退场景, 我们很多页面在用户体验上是要区分是否为后退的.
所以为了解决这个问题我在 router 上面增加了一段逻辑来实现记录路由轨迹, 不同与浏览器记录的历史我们不需要记录用户操作的全部记录. 我们只需要关注用户操作的路由的先后顺序即可.
- import Vue from 'vue'
- import Router from 'vue-router'
- Vue.use(Router)
- let router = new Router({
- routes: [
- ...
- ]
- })
- // 记录用户浏览页面的地址的轨迹
- router.routesArr = []
- // 后退到上一层页面, 不是上一个历史
- router.backward = function (stepNum) {
- typeof stepNum !== 'number' && (stepNum = 1)
- stepNum = Math.abs(stepNum)
- let index = router.routesArr.length - 1 - stepNum
- let route = router.routesArr[0]
- if (index> 0) {
- route = router.routesArr[index]
- }
- router.push({
- name: route.name,
- // path: route.path,
- params: { isBack: true },
- query: route.query
- })
- }
- // 判断某一个路由是否在轨迹中出现
- router.getIndexOf = path => {
- for (let i in router.routesArr) {
- let route = router.routesArr[i]
- if (route.path === path) {
- return i
- }
- }
- return -1
- }
- // 记录用户浏览页面的地址的轨迹, 只保留单一节点
- router.afterEach((to, from) => {
- let index = router.getIndexOf(to.path)
- if (index !== -1) {
- router.routesArr.splice(index, 900)
- }
- router.routesArr.push(to)
- })
- export default router
记录轨迹
- // 记录用户浏览页面的地址的轨迹, 只保留单一节点
- router.afterEach((to, from) => {
- let index = router.getIndexOf(to.path)
- if (index !== -1) {
- router.routesArr.splice(index, 900)
- }
- router.routesArr.push(to)
- })
我们需要记录路由的轨迹, 并且还得保存路由的数据, 不然后退是参数就会丢失了. 这里使用的全局后置钩子函数. 注意了, 每个路由只保留一次, 并且从先后层级上, 只留下当前路由及以前的层级.
这里当页面浏览到已经出现过的页面路由时, 我认为就是后退到某个页面
用户操作为: z->a->b->c->d->b
d->b 就是后退到 b: 轨迹由 z->a->b->c->d 变为 z->a->b
前进事件实话说代码中使用的不多, 这里就不处理了
后退事件并标记
- router.backward = function (stepNum) {
- typeof stepNum !== 'number' && (stepNum = 1)
- stepNum = Math.abs(stepNum)
- let index = router.routesArr.length - 1 - stepNum
- let route = router.routesArr[0]
- if (index> 0) {
- route = router.routesArr[index]
- }
- router.push({
- name: route.name,
- // path: route.path,
- params: { isBack: true },
- query: route.query
- })
- }
这里的后退事件不是浏览器历史了, 而是路由的先后轨迹
然后找到对应后退的路由信息, 利用 push 事件将页面跳转过去, 同时携带数据, 并传递后退标记.
使用
- // 后退
- goback () {
- this.$router.backward()
- }
- // 判断是否为后退
- if (this.$route.params.isBack) {
- this.transitionEffect = ''
- }else {
- this.transitionEffect = 'slideInRight'
- }
来源: https://juejin.im/post/5bd44d70f265da0aa74f7073