背景
以下场景经常会做页面退出拦截
- 编辑表单
思路整理
- 使用路由钩子
beforeRouteLeave来进行页面离开时的拦截,next(false)进行路由切换的阻断从而进行页面跳转的拦截。 - vant的
dialog.confirm组件做离开拦截的样式。 - 定义isLoading来判断页面数据是否已经加载完毕,当页面数据加载完毕后,开启监听。
- 定义isChange来监听页面数据变化。
问题
- 触发路由守卫后,vant的
dialog.confirm组件只能触发一次。再次触发dialog时,无法弹框。
解决问题
- 把
dialog.confirm挂载到一个指定的dom节点上,触发一次dialog,删除一次节点,再次触发重新生成节点。保证每次dialog.confirm都会挂载到一个新的节点下。方法:定义变量dialogShow,来控制挂载节点dialog-container的生成和删除。
代码
<template>
<div class="page-container">
<div v-if="dialogShow" class="dialog-container"></div>
</div>
</template>
export default {
data () {
return {
form: {
name: '',
age: 0,
},
dialogShow: false,
isChange: false,
isLoading: true,
}
},
created () {
...业务数据处理
this.isLoading = false
},
watch: {
form {
handler () {
if (!this.isLoading) {
this.isChange = true
}
},
deep: true
}
},
beforeRouteLeave (to, from, next) {
if (this.isChange) {
this.dialogShow = true
setTimeout(() => {
this.$dialog.confirm({
title:'提示',
message:'您的操作未保存,是否离开此页面?',
confirmButtonText:'继续编辑',
confirmButtonColor:'#00B269',
cancelButtonColor:'#999',
cancelButtonText:'离开',
getContainer:()=>{
return document.querySelector('.dialog-container');
}
}).then(()=>{
this.dialogShow = false
next(false)
}).catch(()=>{
this.dialogShow = false
next()
})
})
} else {
next()
}
}
}