Vant和ElementPlus在vue的hash模式的路由下路由离开拦截使用Dialog和MessageBox失效

问题复现

ElementPlus:当点击返回或者地址栏回退时,MessageBox无效

html 复制代码
<template>
  <div>Element Plus Dialog 路由离开拦截测试</div>
  <el-button type="primary" @click="$router.back()">返回</el-button>
</template>

<script setup lang="ts">
import { onBeforeRouteLeave } from 'vue-router';
import { ElMessageBox } from 'element-plus'

/** 路由拦截 */
onBeforeRouteLeave(async (to, from, next) => {
  try {
    await ElMessageBox.confirm(
    '确定要离开吗',
    {
      cancelButtonText:'取消',
      confirmButtonText:'确定',
      type: 'warning',
    }
  )
    next();
  } catch (error) {
    next(false);
  }
});
</script>

Vant:当点击返回或者地址栏回退时,Dialog第一次生效,第二次开始无法生效

html 复制代码
<template>
  <div>Vant Plus Dialog 路由离开拦截测试</div>
  <van-button type="primary" @click="$router.back()">返回</van-button>
</template>

<script setup lang="ts">
import { onBeforeRouteLeave } from "vue-router";
import { Dialog,Toast } from "vant";

/** 路由拦截 */
onBeforeRouteLeave(async (to, from, next) => {  
  try {
    await Dialog.confirm({
      message: "确定要离开吗",
      confirmButtonColor: "#357ef7",
    });
    next();
  } catch (error) {
    next(false);
  }
});
</script>

失效原因

Vant和ElementPlus的Dialog都有一个当路由地址变化时自动关闭的默认属性(官方文档中有说明)(ElementPlus是当hash变化的时候自动关闭),所以导致我们希望的是Dialog在路由变化的时候生效,但是Dialog在路由地址变化的时候自动小时了,产生了矛盾,所以失效

Vant

ElementPlus

Vant之所以第一次会生效,因为Vant在第一次的时候并未挂载到DOM节点中,导致默认的路由变化关闭Dialog不起作用,但是第二次开始Dialog已经挂载到DOM节点上了,默认路由关闭的属性也就生效了(Vant的Dialog第一次挂载之后不会移除,会通过display属性控制显示隐藏,ElementPlus的MessageBox会动态的挂载和移除,上述GIF的DOM中可以看出二者的差别)

解决方法

方案一:使用history模式

js 复制代码
import {
  createRouter,
  createWebHistory,
  createWebHashHistory,
  RouteRecordRaw,
} from "vue-router";

const router = createRouter({
  history: createWebHistory(),
  // history: createWebHashHistory(),
  routes,
});

方案二:关闭对应的路由变化自动关闭的属性

ElementPlus

js 复制代码
/** 路由拦截 */
onBeforeRouteLeave(async (to, from, next) => {
  try {
    await ElMessageBox.confirm(
    '确定要离开吗',
    {
      cancelButtonText:'取消',
      confirmButtonText:'确定',
      type: 'warning',
      // 禁用路由变化自动关闭
      closeOnHashChange:false
    }
  )
    next();
  } catch (error) {
    next(false);
  }
});

Vant

js 复制代码
/** 路由拦截 */
onBeforeRouteLeave(async (to, from, next) => {  
  try {
    await Dialog.confirm({
      message: "确定要离开吗",
      confirmButtonColor: "#357ef7",
      // 禁用路由变化自动关闭
      closeOnPopstate: false,
    });
    next();
  } catch (error) {
    next(false);
  }
});

注意

上述的时效问题仅在hash模式的路由且并未关闭默认的路由变化自动关闭的属性时生效,history模式并不会失效

相关推荐
90后的晨仔2 小时前
Vue 组件事件完全指南:子父组件通信的艺术
前端·vue.js
正义的大古2 小时前
OpenLayers地图交互 -- 章节十六:双击缩放交互详解
javascript·vue.js·openlayers
Bella_a3 小时前
请描述Vue的生命周期钩子,并在哪个阶段能访问到真实的DOM?
vue.js
小样还想跑3 小时前
UniApp键盘监听全攻略
vue.js·uni-app·计算机外设
_一两风3 小时前
Vue3 常用指令介绍
vue.js
Z_ One Dream3 小时前
React 和 Vue 如何选择?(2026 年)
javascript·vue.js·react.js
Restart-AHTCM3 小时前
前端核心框架vue之(路由核心案例篇3/5)
前端·javascript·vue.js
天蓝色的鱼鱼4 小时前
高效开发之选:六款优秀的Vue3开源后台模板全面解析
前端·vue.js
知识分享小能手10 小时前
React学习教程,从入门到精通,React 单元测试:语法知识点及使用方法详解(30)
前端·javascript·vue.js·学习·react.js·单元测试·前端框架
Ares-Wang12 小时前
Vue3 》》vite》》TS》》封装 axios ,Promise<T>
vue.js·typescript