beforeRouteLeave (to, from, next) {
    //流程页  人为点击保存跳转页面   新增
    if(this.processPage && !this.manToSave && this.type=='add'){
      let issave =  confirm('当前页面没有保存,是否确定要离开?');
      if(issave){   //确定
        next(true);
      }else{     //取消
        next(false);
      }
      
      //自己写的弹窗是否保存   不用了
      // this.initPagination(next);
    }else {next(true)}
  }, 

用confirm(‘当前页面没有保存,是否确定要离开?’); 而不是用自己写的el-ddialog或者弹窗

错误做法:

一开始的时候我是想着使用vuex结合vue router的beforeEach导航守卫来实现。
用户在点击跳转到另一个页面的时候会触发生命周期函数beforeDestroy,如果内容尚未保存,我们就弹出一个提示框,当用户选择取消的时候,就将vuex中的introduceState值更新为true。

</script>
import { mapGetters, mapActions, mapMutations } from "vuex"
export default {
 data() {
  return {
   contentHasSave: false // 记录用户是否已经保存内容
  }
 },
 methods: {
  ...mapMutations({
   changeIntroduceState: changeIntroduceState
  })
 },
 beforeDestory: function(){
  if(!contentHasSave){
   // 使用element的提示框
   this.$confirm('您还未保存简介,确定需要提出吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
   }).then(() => {
    // 选择确定,正常跳转
   })
   .catch(() => {
    // 选择取消
    this.changeIntroduceState(true)
   })
  }
 }
}
</script>

最后在router的beforeEach的导航守卫里监测from为当前页面的所有路由跳转。当state的introduceState为true的时候使用next(false)来取消本次路由跳转

import Vue from "vue";
import VueRouter from "vue-router";
import routeConfig from "./routes";
import {sync} from "vuex-router-sync";
import store from "../store";
//加载路由中间件
Vue.use(VueRouter)
//定义路由
const router = new VueRouter({
 routes: routeConfig,
 //mode: 'history'
})
sync(store, router)
router.beforeEach((to, from, next) => {
 // 简介也未提交,取消跳转
 if(from.fullPath === '/adwords/introduce' && store.state.introduceState === 'not-save'){
  next(false)
 }
})
export default router

这种做法其实是行不通的,因为beforeEach方法的执行其实是在组件beforeDestory的方法之前执行的,也就是说beforeEach执行的时候introduceState的状态值根本没有被更新为true。

vue router的官方文档,找到了一个绝妙的方法,那就是组件内的导航守卫。

beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 this
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 this
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 this
}

实现1:(路由变化时有反应)

</script>
export default {
 data() {
  return {
   contentHasSave: false // 记录用户是否已经保存内容
  }
 },
  // 组件内导航钩子,处理未保存退出的情况
 beforeRouteLeave: function(to, from , next){
  if(this.buttonText === '提交'){
   next(false)
   this.$confirm('您还未保存简介,确定需要提出吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
   }).then(() => {
    // 选择确定
    next()
   })
  }
 }
}
</script>

实现2:(既能在页面跳转也可以在页面关闭时有反应)

  mounted(){
    window.addEventListener("beforeunload", this.actBeforeUnload,false);  

  },
  //离开新增页、编辑页记得解绑,否则其他页面中也会出现提示的效果
  beforeDestroy() {
    window.removeEventListener("beforeunload",this.actBeforeUnload,false);
  },  
  methods: {
    actBeforeUnload(event){
      if(this.processPage && !this.manToSave && this.type=='add'){
        event.returnValue = "我在这写点东西...3357"; 
      }else {
        
      }
    },
 }
Logo

前往低代码交流专区

更多推荐