vue3 离开页面时弹框用户确认或取消,以及hooks封装,在其他页面使用

摘录来自
https://www.jianshu.com/p/7b054af5e3d9

先上html

  <van-dialog v-model:show="confimShow" title="温馨提示" show-cancel-button>
      <p style="color: #484848; text-align: center; margin-top: 10px">
        是否确认退出平台?
      </p>
      <template #footer>
        <div class="btn-group flex align-center justify-between">
          <button class="cancel" @click="cancel">取消</button>
          <button class="confirm" @click="confirm">确认</button>
        </div>
      </template>
    </van-dialog>

这里用到 promise 和 router 和 一个变量来控制

import { onBeforeRouteLeave,useRouter  } from "vue-router";  //vue3使用这个钩子

const confimShow = ref(false); //弹框显示
const out = ref(false) //控制下次离开页面时候是否继续弹框
let resolveFn, rejectFn;  //保存用户确认和取消 的回调
function cancel() {
  rejectFn && rejectFn()
  confimShow.value = false
}
function confirm() {
  resolveFn && resolveFn()
  confimShow.value = false
}

onBeforeRouteLeave(async (to, from, next) => {
  if (out.value) {
    next()  // 如果是true 就不继续弹框
  } else {
    next(out.value) //为false时候,先中断这次路由跳转
    await new Promise((resolve, reject) => {
      resolveFn = resolve  //分别暴露这个promise的
      rejectFn = reject
      setTimeout(() => {
        confimShow.value = true; //显示是否退出弹框 ,这里一定要开多一个 宏任务,微任务不知道行不行,感兴趣的自己试试,我懒。否则弹框不会显示
      }, 20)
    }).then(res => { //如果用户点击确认 就设置true 下次不用弹框
      out.value = true 
      router.back() //这里用 push 或者 back 都行。看个人需求
    }).catch(err => {})
  }
});

封装成hooks的写法如下





import {  ref} from "vue";
import { onBeforeRouteLeave,useRouter  } from "vue-router";  //vue3使用这个钩子
import { ElMessageBox } from 'element-plus';

export function useLeaveCheck(){
const router=useRouter()

const useCheck=ref(false) // 是否需要路由检测拦截
const canLeave = ref(false) //控制下次离开页面时候是否继续弹框



const  showConfirm=()=>{
    ElMessageBox.confirm(
        '数据未保存,是否仍要离开当前页面?',
        '提示',
        {
          confirmButtonText: '直接离开',
          cancelButtonText: '继续编辑',
          type: 'warning',
        }
      ).then(() => {
        canLeave.value=true
        router.back()
      }).catch(() => {
        console.log('继续编辑')
        canLeave.value=false
      })
}


const onChange=()=>{
 
 return onBeforeRouteLeave(async (to, from, next)=>{

  if(useCheck.value){
    if (canLeave.value) {
      next()  // 如果是true 就不继续弹框
    } else {
      next(canLeave.value)
      showConfirm()
    }
  }else{
    next()
  }

  
    
  });
}



return {
  useCheck,
  onChange
}

}

具体页面的使用

import { useLeaveCheck } from "@/hooks/leaveCheck";
const {onChange,useCheck}=useLeaveCheck()
onChange()

const cancel=()=>{
useCheck.value=true
//router.push('xxxxx)
}

const submit=()=>{
useCheck.value=false
//router.push('xxxxx)
}
posted @ 2024-02-29 11:29  风意不止  阅读(1421)  评论(0编辑  收藏  举报