You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js:路由切换前显示确认弹窗的实现方案

Vue路由切换前弹出确认对话框的实现方案

刚好我之前在Vue项目里处理过一模一样的需求,尤其是表单页面用户填了内容没保存就误点跳转的场景,下面给你两种实用的实现方式,按需选择就行:

方案一:单个组件内的路由离开确认(推荐针对特定页面)

如果只有某几个页面需要这个确认逻辑(比如表单编辑页),用组件内的路由离开守卫是最精准的方式,不会影响其他页面。

Vue2 选项式API写法:

export default {
  // 路由离开前的守卫
  beforeRouteLeave(to, from, next) {
    // 这里可以加额外判断,比如表单是否有未保存的修改
    const hasUnsavedChanges = this.formData !== this.initialFormData;
    
    if (hasUnsavedChanges) {
      // 原生确认弹窗
      const confirmLeave = window.confirm('你有未保存的修改,确定要离开吗?');
      if (confirmLeave) {
        next(); // 用户确认,允许跳转
      } else {
        next(false); // 用户取消,阻止跳转,停留在当前页面
      }
    } else {
      next(); // 没有未保存内容,直接放行
    }
  },
  data() {
    return {
      formData: {},
      initialFormData: {}
    };
  },
  mounted() {
    // 保存初始表单数据用于对比
    this.initialFormData = {...this.formData};
  }
};

Vue3 组合式API写法:

import { ref, onMounted } from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
import { ElMessageBox } from 'element-plus';

export default {
  setup() {
    const formData = ref({});
    const initialFormData = ref({});

    onMounted(() => {
      initialFormData.value = {...formData.value};
    });

    // 注册路由离开守卫
    onBeforeRouteLeave((to, from, next) => {
      const hasUnsavedChanges = JSON.stringify(formData.value) !== JSON.stringify(initialFormData.value);
      
      if (hasUnsavedChanges) {
        // 用Element Plus的自定义弹窗(异步场景)
        ElMessageBox.confirm(
          '你有未保存的修改,确定要离开吗?',
          '提示',
          {
            type: 'warning',
            confirmButtonText: '确认离开',
            cancelButtonText: '继续编辑'
          }
        ).then(() => {
          next(); // 确认后放行
        }).catch(() => {
          next(false); // 取消后阻止跳转
        });
      } else {
        next();
      }
    });

    return { formData };
  }
};

方案二:全局路由切换确认(适合全项目或批量页面)

如果需要给大部分页面加上这个确认逻辑,可以用全局前置守卫,在路由配置文件中统一处理:

// router/index.js(Vue2/Vue3通用)
import { createRouter, createWebHashHistory } from 'vue-router';
import { ElMessageBox } from 'element-plus';

const router = createRouter({
  history: createWebHashHistory(),
  routes: [/* 你的路由配置 */]
});

// 全局前置守卫
router.beforeEach((to, from, next) => {
  // 可以配置白名单,排除不需要确认的页面(比如登录页、首页)
  const whiteList = ['/', '/login'];
  if (whiteList.includes(from.path)) {
    next(); // 白名单页面直接放行
    return;
  }

  // 弹出确认对话框
  ElMessageBox.confirm(
    '确定要离开当前页面吗?',
    '提示',
    {
      type: 'info'
    }
  ).then(() => {
    next();
  }).catch(() => {
    next(false);
  });
});

export default router;

关键细节提醒:

  • 如果使用异步弹窗组件(比如Element UI/Plus的MessageBox),一定要在Promise的then或catch回调中调用next(),否则路由会一直处于等待状态。
  • next(false)的作用是阻止当前导航,让页面停留在当前路由;如果调用next()则允许导航继续。
  • 可以根据业务需求添加额外判断(比如表单是否修改过),避免无意义的确认弹窗。

内容的提问来源于stack exchange,提问作者Sagar Kharche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:38:57