问题背景
在Vue 3 + Vue Router项目中,我们经常需要在用户离开页面前进行确认,特别是当表单有未保存的更改时。onBeforeRouteLeave 与 Element Plus 的 ElMessageBox.confirm 结合使用是一个常见方案,但在实际应用中存在不少坑点。
直接上代码
onBeforeRouteLeave(async (to, from, next) => {
if (!modelDirty.value) return next()
try {
await ElMessageBox.confirm('还未保存,离开会丢失,确定继续吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnHashChange: false
})
modelDirty.value = false
next()
} catch (error) {
next(false)
}
})
坑点梳理
坑点1:next() 调用时机问题
问题描述:在异步操作中忘记调用 next(),或者重复调用
javascript
// ❌ 错误示例:可能在某些路径下未调用next
onBeforeRouteLeave(async (to, from, next) => {
if (!dirty) {
// 这里没有调用 next()!
return
}
// ...其他逻辑
})
解决方案:
// ✅ 正确示例:确保所有路径都调用next
onBeforeRouteLeave(async (to, from, next) => {
if (!modelDirty.value) {
next() // 确保这里也调用next
return
}
// ...其他逻辑
})
坑点2:closeOnHashChange 设置的必要性
问题描述:用户点击浏览器前进/后退按钮时,hash变化可能导致MessageBox意外关闭
解决方案:
// ✅ 必须设置 closeOnHashChange: false
await ElMessageBox.confirm('提示内容', '标题', {
// ...其他配置
closeOnHashChange: false, // 防止路由hash变化自动关闭
closeOnClickModal: false, // 防止点击遮罩层关闭
closeOnPressEscape: false // 防止ESC键关闭(可选)
})