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>
相关推荐
这是个栗子15 小时前
【Vue代码分析】前端动态路由传参与可选参数标记:实现“添加/查看”模式的灵活路由配置
前端·javascript·vue.js
刘一说15 小时前
Vue 动态路由参数丢失问题详解:为什么 `:id` 拿不到值?
前端·javascript·vue.js
方也_arkling15 小时前
elementPlus按需导入配置
前端·javascript·vue.js
爱吃大芒果16 小时前
Flutter for OpenHarmony 实战: mango_shop 资源文件管理与鸿蒙适配
javascript·flutter·harmonyos
David凉宸16 小时前
vue2与vue3的差异在哪里?
前端·javascript·vue.js
Irene199116 小时前
JavaScript字符串转数字方法总结
javascript·隐式转换
css趣多多16 小时前
this.$watch
前端·javascript·vue.js
Code小翊16 小时前
JS语法速查手册,一遍过JS
javascript
子春一17 小时前
Flutter for OpenHarmony:构建一个 Flutter 天气卡片组件,深入解析动态 UI、响应式布局与语义化设计
javascript·flutter·ui
Remember_99317 小时前
Java 单例模式深度解析:设计原理、实现范式与企业级应用场景
java·开发语言·javascript·单例模式·ecmascript