Writing in the front

The idea and implementation of anti-shake and throttling are relatively simple, and the concept of closure is clarified in the implementation process. However, when used in vUE project, there were some problems, such as not calling correctly, not using singletons and so on. After understanding, write down how to use it

1. Debounce

1. The function is executed only once within n seconds after the high-frequency event is triggered. If the high-frequency event is triggered again within n seconds, the time is recalculated.

To put it simply, no matter how many clicks are made within a certain period of time, only the last call will be made. The ones in front will be cleared

2. Direct implementation in methods

debounce (func, delay = 1000, immediate = false) {
  / / closures
  let timer = null
  // Arrow functions cannot be used
  return function () {
    if (timer) {
      clearTimeout(timer)
    }
    if(immediate && ! timer) { func.apply(this.arguments)
    }
    timer = setTimeout(() = > {
      func.apply(this.arguments)
    }, delay)
  }
},
Copy the code

Use 3.

<template>
  <el-input v-model="text" @input="debounceInput" />
</template>

<script>
  export default {
    mounted () {
      this.debounceInput = this.debounce(this.handle, 1000.false)
    },
    data () {
      return {
        text: ' '.debounceInput: () = >{},}},methods: {
      handle (value) {
        console.log(value)
      },

      debounce (func, delay = 1000, immediate = false) {
        let timer = null
        // Arrow functions cannot be used
        return function () {
          // The previous scheduled tasks need to be cleared when repeated calls are made in time
          if (timer) {
            clearTimeout(timer)
          }
          // For the first time to execute immediately
          if(immediate && ! timer) { func.apply(this.arguments)
          }
          timer = setTimeout(() = > {
            func.apply(this.arguments)
          }, delay)
        }
      },
    }
  }
</script>
Copy the code

4. The rendering

Ii. Throttle

1. After a high-frequency event is triggered, the function is executed only once within n seconds

To put it simply, no matter how many times you click within a certain period of time, only the first time will be executed and the rest will return directly

2. Implement in utils.js (timestamp version)

export const throttle = (fn, delay = 1000) = > {
  // Since last execution time
  let lastTime = 0
  return function () {
    let _this = this
    let _arguments = arguments
    let now = new Date().getTime()
    // Can be executed again if the delay has exceeded the previous execution
    if(now - lastTime > delay){
      fn.apply(_this,_arguments)
      lastTime = now
    }
  }
}
Copy the code

3. Introduce it into VUE

<template>
  <el-input v-model="text" @input="throttleInput" />
</template>

<script>
  import {throttle} from '.. /utils'
  export default {
    name: 'throttle',
    data () {
      return {
        text: ' ',}},methods: {
      handle (value) {
        console.log(value)
      },

      throttleInput: throttle(function (. args) {
        this.handle(... args) }) } }</script>
Copy the code

4. The rendering

There is a slight flaw in this throttling effect. If the time difference between the last execution and the next user input is within the delay, the input result will not be printed

Third, optimization of throttling

  1. If the time difference between the last execution and the next user operation is within the delay, the operation will be abandoned. Therefore, we need to generate a timer within this period to ensure that the operation will be executed. If the delay time is exceeded, the operation can be directly executed
export const throttle = (fn, delay = 2000) = > {
  let lastTime = 0, timer = null

  return function () {
    let _this = this
    let _arguments = arguments
    let now = new Date().getTime()
    clearTimeout(timer)
    // Determine whether the difference between the last triggering time and the current triggering time is smaller than delay and create a timer
    if (now - lastTime < delay) {
      timer = setTimeout(function () {
        lastTime = now
        console.log("Actuator trigger")
        fn.apply(_this, _arguments)
      }, delay)
    } else {
      // Otherwise, it can be executed directly
      lastTime = now
      console.log("Direct trigger")
      fn.apply(_this, _arguments)
    }
  }
}
Copy the code
  1. rendering

Finally: closures

I have seen the concept of closure before, but the literal translation is confusing and various explanations are complicated. Now I have realized what closure is. In Java, for example, a closure is a private variable that can be accessed through a public method.