检测浏览器关闭或页面更改VueJs

时间:2019-12-19 12:57:31

标签: vue.js vuejs2

我尝试检测用户何时在输入中进行更改/插入,并且他尝试更改/关闭页面以向他发出警告。我做了一些研究,但到现在为止我什么都没找到。

<b-form-group label="Name" label-for="name-input">
<b-form-input
        id="name-input"
        v-model="name"
></b-form-input>
</b-form-group>

created() {
    document.addEventListener('beforeunload', this.handlerClose)
},
handlerClose: function handler(event) {
    console.log('CHANGE!!!!');
},

2 个答案:

答案 0 :(得分:1)

更简单的方法是简单比较所选数据的字符串化JSON。如果它们相等,那么我们知道用户尚未更改/更新/更改数据。

这是一个简单的设置:

  1. 创建一种方法,该方法为要观察更改的用户数据生成JSON。
  2. 创建compoonent / app后,您将缓存创建的数据并存储/缓存
  3. 创建一个仅返回用户数据和缓存的用户数据的当前状态的计算属性
  4. 然后在beforeunload处理程序中,您可以检查此计算属性的返回值,以确定用户是否已对数据进行突变。

请参见下面的概念验证:

new Vue({
  el: '#app',
  
  // COMPONENT DATA
  data: {
    // Dummy data
    firstName: 'John',
    lastName: 'Doe',
    
    // Cache form data
    cachedFormData: null,
  },
  
  // COMPONENT LIFECYCLE HOOK
  created: function() {
    // Create a cache when component/app is created
    this.cachedFormData = this.formDataForComparison();
    
    document.addEventListener('beforeunload', this.handlerClose);
  },
  
  // COMPUTED PROPERTIES
  computed: {
    // Compares cached user data to live data
    hasChanged() {
      return this.cachedFormData !== this.formDataForComparison();
    }
  },
  
  // COMPONENT METHODS
  methods: {
    // Callback handler
    handlerClose: function() {
      if (this.hasChanged) {
        // Logic when change is detected
        // e.g. you can show a confirm() dialog to ask if user wants to proceed
      } else {
        // Logic when no change is detected
      }
    },
    
    // Helper method that generates JSON for string comparison
    formDataForComparison: function() {
      return JSON.stringify({
        firstName: this.firstName,
        lastName: this.lastName
      });
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <input type="text" v-model="firstName" />
  <input type="text" v-model="lastName" />
  <br />
  <br />
  <span>Has user changed data? <strong>{{ hasChanged }}</strong></span>
</div>


另一种方法是,另一种方法是简单地存储基态为false的标志。每当在元素上检测到输入/更改事件时,标志状态便切换为true。但是,此方法有几个缺点:

  1. 即使用户撤消他/她的更改,它仍将标记为已更改。这构成了误报。
  2. 您将需要将监视程序绑定到所有v-model成员,或者将输入/更改事件侦听器绑定到页面上的所有输入元素。如果您的表单很大,那么您可能会忘记对输入元素执行此操作。

答案 1 :(得分:1)

检测导航到其他页面或关闭页面

您可以尝试在窗口对象而不是文档对象上使用相同的事件处理程序beforeunload,例如MDN Web文档(https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event)中所述。该事件应处理两种情况,切换页面和关闭页面。

<script>
  export default {
    created() {

      window.addEventListener('beforeunload', (event) => {
        // Cancel the event as stated by the standard.
        event.preventDefault();
        // Chrome requires returnValue to be set.
        event.returnValue = '';
      });

    }
  }
</script>

此事件使网页能够触发一个确认对话框,询问用户是否真的要离开该页面。如果用户确认,浏览器将导航到新页面,否则将取消导航。

关于您要检测到是否有任何变化的第二个问题:该事件处理程序没有检测到变化。

为了保持状态,用户进行了更改,例如转换为表单,我将使用数据道具isChanged将此状态外包,并使用false对其进行初始化。然后使用Vue指令v-on:changev-on:input将道具从false更改为true

<template>
  <div>
    <input type="text" @change="userMadeChange" v-model="inputText" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputText : "",
      isChanged : false
    }
  },
  methods : {
    userMadeChange() {
      this.isChanged = true;
    }
  }
}
</script>