js vue 下的防抖和节流

1,343 阅读3分钟

场景1:input搜索 (防抖debounce)

定义: 所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

具体场景:vue input输入,每输入一个值都会触发@input函数,然后发起ajax保存(或者搜索)输入值。输入太快太多的话,就会造成同时发送很多请求

理想状态: 下是希望输入了一段时间后,才去发起ajax

理解不了的话就记住 input 搜索、存值等就是`防抖`

网上有很多防抖的函数,比如立即执行和非立即执行

1. 非立即执行(其实就是夸夸一顿输入停下后,延后3秒才执行)

input 的搜索、存值都是使用的非立即执行版本,timeout 在vue中一定要是全局变量

<input type="text" @input="saveTitle">

data(){
    return {
        timeout:null,
    }
}
methods:{
    saveTitle(){
     if (this.timeout) clearTimeout(this.timeout);
        this.timeout = setTimeout(() => {
          this.saveDocs();
        }, 3000);
    }
}

2. 立即执行(每次输入的第一下发请求,一直输入一直不发)

立即执行的现象是:输入1,就发请求,此时value是1,然后继续输入了23456,不会再发请求。停3秒以上(比如等待时间是3秒),在输入7 的时候,发请求,此时value是1234567,所以每次的value都是不符合的,因此不适合。

function debounce(func,wait) {
    let timeout;
    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);

        let callNow = !timeout;
        timeout = setTimeout(() => {
            timeout = null;
        }, wait)

        if (callNow) func.apply(context, args)
    }
}

场景2:提交保存按钮 (节流throttle)

所谓节流,就是指连续触发事件但是在n秒中只执行一次函数。节流会稀释函数的执行频率。

具体场景:点击+ 创建一个新文件,点完请求没回来,但是用户无感知,以为没点上就继续点,就会在只想创建一个的情况下, 可能就创建了3个文件。

理想: 希望一段时间内点击多次,但是只执行一次

1. 时间戳版本(点击立即执行)

提交按钮多次点击只提交一次 就是使用的时间戳版本节流

data(){
    return {
        previous:0
    }
}
createFile() {
  let now = Date.now();
  if (now - this.previous > 4000) {
    console.log("发请求")
    this.previous = now;
  }
}

可以看到,在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。

2. 定时器版本(点击延后4秒执行)

function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}

可以看到,在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次,在停止触发事件后,函数还会再执行一次。

总结:

从原理上来说是根据你的场景选择适合你的方式。 但是如果你实在记不住, 或者小白阶段,还不是很理解,就记住

  1. input搜索 用非立即执行版本的防抖
  2. 按钮提交 用 时间戳版本的节流
  3. vue中 timeout 和previous 是全局变量
  4. 如果函数执行结果不理想,检查this指向问题

推荐文章写的很好防抖节流