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
相关产品推荐
相关产品推荐

