场景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 执行一次,在停止触发事件后,函数还会再执行一次。
总结:
从原理上来说是根据你的场景选择适合你的方式。 但是如果你实在记不住, 或者小白阶段,还不是很理解,就记住
- input搜索 用
非立即执行版本的防抖 - 按钮提交 用
时间戳版本的节流 - vue中 timeout 和previous 是
全局变量 - 如果函数执行结果不理想,检查this指向问题
推荐文章写的很好防抖节流