H5游览器自带返回的问题处理Vue3

452 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

前言

以前不知道vue3的vue-router 的组件守卫钩子这么好用,在这边记录一下自己遇到的关于h5再带返回按钮的bug问题。。。

v2-3307560f1b146f6fc87ad4bbeff367ff_720w.png

一.问题整理

  1. 点返回键需要给出提示信息确认后再返回上一页
  2. 遇到页面route传参,点击返回会留下记录返回上一页的情况

1:点返回键需要给出提示信息确认后再返回上一页

之前百度搜到最多的答案就是用如下这种方式:

const backChange = (e) => {
        console.log('1', window.history.length)

        Dialog.confirm({
          title: '提示',
          message: '您的合同还未提交,是否确认离开?\n(离开后编辑的信息将不会保存)',
          confirmButtonText: '确认离开',
          cancelButtonText: '我再想想'
        })
          .then(() => {
            // on confirm
            console.log('2', window.history.length)
            window.removeEventListener('popstate', backChange, false)
            // window.location.href = back.value
            // window.history.back()
            router.go(-2)
          })
          .catch((e) => {
            // on cancel
            history.pushState(null, null, location.href)
            window.removeEventListener('popstate', backChange, false)
            window.addEventListener('popstate', backChange, false)
          })
      }

      onMounted(() => {
        if (window.history && window.history.pushState) {
          var state = {
            title: 'title',
            url: ''
          }
          history.pushState(state, 'title', '')
          window.addEventListener('popstate', backChange, false)
        }
      })
      onUnmounted(() => {
        window.removeEventListener('popstate', backChange, false)
      })

这种方式总结一句话:真麻烦,代码量多还需要计算回退的次数,这边建议大家看看就好,掘金上有一个文章专门有讲到怎么计算的,我贴个链接:

单页应用巧用history.go()、history.length返回到历史指定页面 - 掘金

最好的方式如下:

onBeforeRouteLeave(async (to, from) => {
        if (to.path.indexOf('/xxx/index') > -1) {
          try {
            return await backChange()
          } catch (e) {
            return false
          }
        }
      })

  const backChange = () => {
        return new Promise((resolve, reject) => {
          Dialog.confirm({
            title: '提示',
            message: '您的合同还未提交,是否确认离开?\n(离开后编辑的信息将不会保存)',
            confirmButtonText: '确认离开',
            cancelButtonText: '我再想想',
            closeOnPopstate: false //这个必须加上不然不起作用
          })
            .then(() => {
              resolve()
            })
            .catch((e) => {
              reject()
            })
        })
      }

是不是美滋滋的方法!建议大家好好看看vue的路由,基础不好碰到的坑就会多多!

提示 : 像onBeforeRouteLeave这个方法在组件v-if内切换不同的子组件,h5自带返回的情况也可以使用!

导航守卫 | Vue Router​router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%8F%AF%E7%94%A8%E7%9A%84%E9%85%8D%E7%BD%AE-api


2:遇到页面route传参,点击返回会留下记录返回上一页的情况

遇到这种我是因为遇到这样的一个业务场景比如:页面a->b->c ,a到b需要传参数,b->c路由也需要传参数,但是最后c->b->a 返回的时候,c->b传参数导致,路由会增加新的记录,这边你会说用replace来改变,但是你可知道,b->c ,c->b这两个页面都用到replace的话,会导致我c返回直接返回a的情况,所以问题又来了,该怎么解决呢,附上代码:注意记得b->c 用push ,c->b用replace

onBeforeRouteUpdate(to => {
    router.go(-1)
})

简简单单一行代码搞定!

当然也可以按照官网另外一种方法,对同一个组件中参数的变化做出响应的话,你可以简单地 watch$route对象上的任意属性,就是$route.params或$route.query:

created() {
    this.$watch(
      () => this.$route.params,
      (toParams, previousParams) => {
        // 对路由变化做出响应...
      }
    )
  },