bug 记录 - 路由守卫 beforeRouteLeave 与 confirm 结合,不生效问题

需求说明

  • 每次离开页面前,需要弹窗提示页面内容未保存
  • 原始代码
javascript 复制代码
beforeRouteLeave(to, from, next) {
  Dialog.confirm({
    title: "标题",
    message: "退出当前页将丢失未保存内容",
    confirmButtonText: "留在当前",
    cancelButtonText: "确定退出",
  })
    .then(() => {
      next(false);
	})
    .catch(() => {
      next();
    });
},

发现问题

  • 第一次离开页面时,触发路由守卫,confirm 生效弹出。
  • confirm 选择"留在当前"时,即执行 next(false)
  • 再次离开页面时,触发路由守卫,但是 confirm 并未弹出,当前页面闪动。

问题解决

  • 只要进入路由守卫,优先拦截下来,然后再进行后续的操作,手动做一个延时
javascript 复制代码
beforeRouteLeave(to, from, next) {
  next(false);
  setTimeout(() => {
    Dialog.confirm({
      title: "标题",
      message: "退出当前页将丢失未保存内容",
      confirmButtonText: "留在当前",
      cancelButtonText: "确定退出",
    })
      .then(() => {})
      .catch(() => {
        next();
      });
  }, 100);
},

完整案例

  • 另外可添加一些变量,用于标识,当前页面是否编辑过,或者退出页面时是否需要拦截
html 复制代码
<template>
  <div>
    <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="活动名称">
        <el-input v-model="form.name"></el-input>
      </el-form-item>
      <el-form-item label="活动区域">
        <el-select v-model="form.region" placeholder="请选择活动区域">
          <el-option label="区域一" value="shanghai"></el-option>
          <el-option label="区域二" value="beijing"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">立即创建</el-button>
        <el-button>取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { Dialog } from "vant";

export default {
  data() {
    return {
      form: {
        name: "",
        region: "",
      },
      lockFlag: false, // 锁 - 优先级最高的
    };
  },
  computed: {
    isEdit() {
      // 当前页面是否编辑过?
      let flag1 = this.form.name;
      let flag2 = this.form.region;
      return flag1 || flag2 ? true : false;
    },
  },
  beforeRouteLeave(to, from, next) {
    if (this.lockFlag) {
      // 一些不需要判断编辑状态的场合
      next();
    } else if (this.isEdit) {
      // 当前页面编辑过,先拦截住
      next(false);
      setTimeout(() => {
        Dialog.confirm({
          title: "标题",
          message: "退出当前页将丢失未保存内容",
          confirmButtonText: "留在当前",
          cancelButtonText: "确定退出",
        })
          .then(() => {})
          .catch(() => {
            next();
          });
      }, 100);
    } else {
      // 在当前页没做操作,直接走了
      next();
    }
  },
  methods: {
    onSubmit() {
      // 走个提交接口
      setTimeout(() => {
        this.$message({
          message: "保存成功",
          type: "success",
        });
        this.lockFlag = true; // 如果是保存成功,退出当前页时,就不要再进行编辑与否的判断了
        this.$router.back();
      }, 100);
    },
  },
};
</script>
相关推荐
m0_471199633 小时前
【vue】通俗详解package-lock文件的作用
前端·javascript·vue.js
今天不要写bug3 小时前
vue项目基于vue-cropper实现图片裁剪与图片压缩
前端·javascript·vue.js·typescript
咬人喵喵4 小时前
14 类圣诞核心 SVG 交互方案拆解(附案例 + 资源)
开发语言·前端·javascript
韩曙亮5 小时前
【Web APIs】元素滚动 scroll 系列属性 ② ( 右侧固定侧边栏 )
前端·javascript·bom·window·web apis·pageyoffset
珑墨5 小时前
【浏览器】页面加载原理详解
前端·javascript·c++·node.js·edge浏览器
FreeBuf_5 小时前
Next.js 发布扫描工具:检测并修复受 React2Shell 漏洞(CVE-2025-66478)影响的应用
开发语言·javascript·ecmascript
馬致远5 小时前
Vue -组件入门
javascript·vue.js·ecmascript
御形封灵6 小时前
基于原生table实现单元格合并、增删
开发语言·javascript·ecmascript
Irene19916 小时前
Prettier 配置文件 .prettierrc.js 和 .prettierrc.json 的区别
javascript·json