在实际应用中,运营人员在编辑数据时不希望因不小心点击了浏览器的回退或刷新按钮导致花费了很长时间编辑的数据丢失。可以采用以下两种手段防止运营编辑时丢失数据:

  • 在运营人员刷新页面或回退时,自动保留数据至浏览器端本地存储,在重新进入编辑页面时再将数据从本地存储中加载到编辑界面。
  • 第二种方法是在运营人员刷新或回退时,强提示运营人员有修改的数据尚未保存,询问是否继续。

无认采用哪一种方式,在技术实现上,我们需要首先能够监听到用户执行回退或刷新页面的动作。

实际上,当用户执行页面刷新时,会触发window对象上的onBeforeUnload事件。所以,我们需要在页面加载时开始监听此事件。在Vue.js应用中,我们可以在Vue.js的mounted生命周期事件函数中开始监听。

  mounted() {
    window.onbeforeunload = e => {
      if (!this.modified) {
        return;
      }

      // 通知浏览器不要执行与事件关联的默认动作
      e.preventDefault();
      // Chrome 需要 returnValue 被设置成空字符串
      e.returnValue = '';
    };
  },

有了以上的代码,只要我们在修改了数据以后,将modified的值改为true,则可以在刷新整个页面时弹出如下提示:

前端技术之:Vue.js应用回退或刷新界面时提示用户保存修改-LMLPHP

当用户点击上述对话框的[取消]按钮后,会取消刷新动作,当用户选择[重新加载]后,浏览器会强制进行页面的刷新。

由于在Vue.js应用中,通常是一个页面的应用,所有的子页面享用一个window对象,所以,如果在一个Vue.js页面组件中增加了对onBeforUnload事件的监听,则可能会影响其它页面组件的相关行为,而在其他页面(如,仅浏览数据的页面)是不希望进行相关的提示的,所以,我们需要在Vue.js组件卸载的时候取消对onBeforeUnload事件的监听。

  destroyed() {
    // 取消对事件的监听
    window.onbeforeunload = null;
  },

用户除了通过浏览器刷新操作退出外,还有两种可能的退出途径:

  • 点击浏览器的前进或回退操作按钮
  • 点击单页面中的前端路由链接

对于以上两种退出途径,onBeforeLoad事件通常是拦截不到相应的事件的,因为这两种操作一般是前端路由的行为。

既然是前端路由的行为,我们就需要在前端路由事件上下功夫。可喜的是,前端路由vue-router为我们提供了导航守卫的能力。关于vue-router导航守卫的相关知识,大家可以参考:vue-router前端路由导航守卫

前端路由导航守卫分为全局守卫、独享守卫、组件内守卫等。这里我们使用的是组件内守卫。

组件内守卫有以下三种

  • beforeRouteEnter 组件第一次被渲染时调用
  • beforeRouteUpdate 路由改变但组件被复用时调用
  • beforeRouteLeave 导航离开组件时调用

显而易见,我们需要监听并处理beforeRouteLeave事件。

  beforeRouteLeave(to, from, next) {
    if (!this.modified) {
      next();
      return;
    }

    this.$confirm('当前页面数据未保存,确定要离开?', '提示', { type: 'warning' })
      .then(() => {
        next();
      })
      .catch(() => {
        next(false);
      });
  },

有了以上的代码,当我们在进行路由切换时(点击浏览器回退按钮或点击页面中的其它路由链接)就会提示如下的对话框:

前端技术之:Vue.js应用回退或刷新界面时提示用户保存修改-LMLPHP

当用户选择取消时,回到原界面,当用户点击确定按钮后,页面强制刷新。

>以上是本人在实际项目应用中遇到的问题及我们采取的解决方案,如果您有更好的方法,或者有更好的建议,欢迎不吝赐教。
11-24 10:19