A recent business issue involved the need for an online training system to know how long users are tracking a preview of an online preview page. In the initial stage, we first thought of using the life cycle functions mounted and Destroyed on the Vue page to add the logic of starting timing and removing timing respectively, and report the corresponding time data of training materials through the background interface, so as to achieve the purpose.

With that in mind, we can start planning the concrete code.

Define the start – end timing function

In data we define the timer as a variable so that it can be accessed anywhere through this.timer so that it can be cleaned up later when the page is destroyed.

Duration Specifies the duration count variable, initialized to 0, in seconds or milliseconds based on the second interval parameter of the timer.

export default {
  data() {
    return {
      timer: null.duration: 0}},methods: {
    startTimer() {
      this.timer = setInterval(() = > {
        console.log('Watching time:'.this.duration)
        this.duration++
      }, 1000)},stopTimer() {
      clearInterval(this.timer)
      this.updateViewHistory() // Report data interface
    },
    updateViewHistory() {
    // Report the interface logic code. }}}Copy the code

In the startTimer function we print out the duration variable incidentally to verify that the displayed time is correct.

How and where

Now that we’ve defined the methods that start and end, we need to start thinking about where to call them. Because the preview page content is not unique, is based on the id of the material to get details for rendering. If we write the startTimer in the Mounted lifecycle, we will not be able to switch the logic we want when we visit pages with different ids.

So I chose to listen for the ID parameter in the route to get the logic to switch the start and end when previewing different pages

watch: {
    $route: {
      immediate: true,
      handler(to, from) {
        if (to.params.id) this.trainingId = to.params.id
        this.startTimer()
      }
    }
  }
Copy the code

The start time method is called, and finally we can see the current time output in the console log

Then, as a final step, we need to call stopTimer when the page is destroyed to clear the timer and report the data.

Since our preview page is a separate TAB opened through window.open, we are listening through the Destroyed lifecycle function. If the jump is routed, you need to destroy it when you leave the page, so that you can listen in through destroyed.

  mounted() {
    window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
  },
  destroyed() {
    window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
  }
Copy the code

The stopTimer method is called indirectly through the window listener method

methods: {
    beforeunloadHandler (e) {
      this.stopTimer()
    }
}
Copy the code

One might ask why not call the stopTimer method directly from within the Destroyed so that the specific logic is separated from the rest of the destroyed logic. Improve code readability and maintainability.

When writing code, we should not only implement the function, but also think a little more. This is the difference between the average and the expert.