vue2 + vant 页面离开拦截

573 阅读1分钟

背景

以下场景经常会做页面退出拦截

  • 编辑表单

image.png

思路整理

  1. 使用路由钩子beforeRouteLeave来进行页面离开时的拦截,next(false)进行路由切换的阻断从而进行页面跳转的拦截。
  2. vant的dialog.confirm组件做离开拦截的样式。
  3. 定义isLoading来判断页面数据是否已经加载完毕,当页面数据加载完毕后,开启监听。
  4. 定义isChange来监听页面数据变化。

问题

  1. 触发路由守卫后,vant的dialog.confirm组件只能触发一次。再次触发dialog时,无法弹框。

解决问题

  1. 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()
        }
        
    }
    
}