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>
相关推荐
糖墨夕1 小时前
第一章:为什么你要学 AI Agent?—— 从"切图仔"到全栈的进化之路
前端·javascript·vue.js
自律懒人2 小时前
ChatGPT Work 上线当天实测:GPT-5.6 Sol 把 Codex 塞进桌面应用,跨应用自动做报表和 PPT,一个指令干 3 小时的活
javascript·开源
不听话坏11 小时前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript
小二·12 小时前
React 19 + Next.js 15 现代前端开发实战:App Router / Server Components / 流式渲染
前端·javascript·react.js
CHNE_TAO_EMSM14 小时前
Android studio 打开文件时自动下载源码
前端·javascript·android studio
竹林81816 小时前
从 ethers.js 迁移到 Viem:一个签名验证 Bug 让我彻底放弃旧爱
javascript
你挚爱的强哥16 小时前
Vue2 实现 1.5s 十连击监听(连续点击若干次),封装通用可复用点击检测工具,不用 data!Vue 封装通用连击监听方法,支持自定义时长与点击次数
前端·javascript·vue.js
半个落月17 小时前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端
天外天-亮17 小时前
HBuilder X 使用 uview-plus 方式
开发语言·javascript·hbuilder x·uview-plus
我有满天星辰18 小时前
Vue项目脚手架之争:create-vue与Vue CLI全面对比
前端·javascript·vue.js