uniapp h5 返回上一页前弹出提示弹窗,确定才允许返回

893 阅读1分钟

阻止页面回退,与替换当前页面

在我们h5项目提交表单页面中,

  1. 通常会使用到拦截当前页面回退,提示用户提交表单。
  2. 提交表单后新的页面替换当前页面

本文是解决拦截表单提交,以及提交表单后替换当前路由栈的一点思路,本文是本人粗鄙的想法,有其他思路的欢迎在评论区交流

export function userHistoryHooks() {
  // 回退的定时事件
  let timer = null
  onMounted(() => {
    /* 这里使用setTimeout以为在进入后一个页面的时候,
      如果希望替换当前页面的时候,需要history.back进行回退,
      回退后会触发onMounted事件,导致阻止监听事件一直被添加

    */
    timer = setTimeout(() => {
      // 添加一个空的路由栈
      window.history.pushState(null, null, document.URL)
      // 添加路由退出事件监听
      window.addEventListener('popstate', onBack, false)
    }, 100)
  })
  function onBack() {
    uni
      .showModal({
        title: '确认要离开吗?',
        content: '表单信息还未提交完成,确认要离开?',
        confirmText: '继续填写',
        cancelText: '离开',
      })
      .then((res) => {
        if (res.confirm) {
          // 添加一个空的路由栈,防止点击返回直接导致页面退出
          window.history.pushState(null, null, document.URL)
          return
        }
        window.removeEventListener('popstate', onBack, false)
      })
  }

  onUnmounted(() => {
    if (timer) {
      clearTimeout(timer)
    }
    window.removeEventListener('popstate', onBack, false)
  })
  function removePopstate(isBack?: boolean) {
    window.removeEventListener('popstate', onBack, false)

    // 这里为什么-1,以为这里要在添加了一个空的路由栈
    window.history.go(-1)
  }
  // 替换当前页面
  function replace(url: string) {
    removePopstate(true)
    setTimeout(() => {
      uni.redirectTo({
        url,
      })
    }, 10)
  }

  return { removePopstate, toPage }
}