(解决方案) 触发物理返回键,切换页面组件但不跳转页面

示例GIF图

最近项目中遇到了一个需求:在下单页中的底部弹层使我们的组件,以解耦的方式运行在别的项目组的页面中(下单页),此时在弹层出来的时候,使用物理返回,就会跳转到“确认订单”页面的上一个页面,不符合操作逻辑。
✋ 本次优化:在使用物理返回的时候,只触发组件的返回组件的上一级,不要触发页面级别的后退。

1. 方案1:使用 vue-router 的 beforeRouteLeave

最初想的方案的确就是beforeRouteLeave,但是实现起来的时候,发现好像没有效果,根本控制不住router的变化。后来实验了一波,发现这个钩子只能作用在router指定路由时的页面上,而该页面的组件如果使用该钩子,是没有效果的,下面是实验的代码:

实验代码

2. 方案2: 自己设置history.state(因为我们的路由采用的是history模式),自己监听popstate,自己编写业务代码触发。

(1)工具类
const HISTORY_STATE = '_history_state_mutou_'

/**
 * 页面记录栈
 */
class PageStack {
  constructor() {
    // 本地存储一份记录,因为history在pop的时候,得不到是哪一条记录被pop掉了
    this.localStack = []
  }
  /**
   * 获取history中的栈
   */
  getHistoryStack() {
    return get(history, `state.${HISTORY_STATE}`, [])
  }
  /**
   * 向栈中压入一条记录
   * @param {*} name 记录名称
   */
  pushState(name) {
    if (this.localStack.includes(name)) {
      return
    }
    this.localStack.push(name)
    history.pushState(
      { ...(history.state || {}), [HISTORY_STATE]: this.localStack },
      document.title
    );
  }
  /**
   * 触发history的pop
   */
  popState() {
    history.go(-1)
  }
  /**
   * 开启监听
   * @param {*} callback 回调
   */
  observePop(callback) {
    const listener = (event) => {
      const popName = this.localStack.pop()
      callback(popName)
    }
    window.addEventListener('popstate', listener)
    return () => {
      window.removeEventListener('popstate', listener)
      const length = this.localStack.length
      length && window.history.go(-length)
      this.localStack = []
    }
  }
}

export const pageStack = new PageStack()
(2)在业务中使用
mounted() {
    pageStack.pushState(PAGE_STACK_NAMES.ONE_PAGE)
    this.clearPageListener = pageStack.observePop((name) => {
      if (name === PAGE_STACK_NAMES.TWO_PAGE) {
        // 触发事件...
      }
      if (name === PAGE_STACK_NAMES.ONE_PAGE) {
        // 触发事件...
      }
    })
  },
  beforeDestroy() {
    this.clearPageListener && this.clearPageListener()
  },

以上大概就是实现的方式的代码,逻辑其实并不复杂,使用history的特性做了一些代码封装,让其好使一些。

参考资料:
https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState