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


    注意:ElementPlus仅在路由模式为Hash时会失效,Vant无论是Hash模式还是History模式均会失效,原因在于他们监听路由变化的原理不同

    ElementPlus的路由回退自动关闭监听的是hashchange事件,而Vant监听的是popstate事件,hashchang事件仅会在路由的hash部分发生变化时才会被触发,而popstate事件只要历史记录发生变化就会被触发(包括通过用户的前进、后退操作,以及通过 JavaScript 中的 pushState()、replaceState() 方法修改历史记录),这也就导致了ElementPlus为什么只会在Hash模式下的路由才会失效,而History模式却不生效。

    ElementPlus
    在这里插入图片描述
    Vant
    在这里插入图片描述

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

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述

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

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

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

    Vant
    在这里插入图片描述

    ElementPlus
    在这里插入图片描述

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

    解决方法
    方案一:使用history模式

    import {
      createRouter,
      createWebHistory,
      createWebHashHistory,
      RouteRecordRaw,
    } from "vue-router";
    
    const router = createRouter({
      history: createWebHistory(),
      // history: createWebHashHistory(),
      routes,
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    /** 路由拦截 */
    onBeforeRouteLeave(async (to, from, next) => {
      try {
        await ElMessageBox.confirm(
        '确定要离开吗',
        {
          cancelButtonText:'取消',
          confirmButtonText:'确定',
          type: 'warning',
          // 禁用路由变化自动关闭
          closeOnHashChange:false
        }
      )
        next();
      } catch (error) {
        next(false);
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Vant

    /** 路由拦截 */
    onBeforeRouteLeave(async (to, from, next) => {  
      try {
        await Dialog.confirm({
          message: "确定要离开吗",
          confirmButtonColor: "#357ef7",
          // 禁用路由变化自动关闭
          closeOnPopstate: false,
        });
        next();
      } catch (error) {
        next(false);
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    Simple WPF: S3实现MINIO大文件上传并显示上传进度
    论文阅读_大语言模型_Llama2
    SpringBoot 整合 RabbitMQ 实现三种模式 (一)有图 有源码
    生命在于研究——CVE-2021-22214记录
    MSDC 4.3 接口规范(27)
    【无标题】
    《Neo4j全站开发》笔记
    SpringMvc静态资源映射
    运行栏在弹窗上面的时候才能控制弹窗,怎么解决
    《HelloGitHub》第 95 期
  • 原文地址:https://blog.csdn.net/weixin_46535880/article/details/133935800