防抖
- 用户触发事件过于频繁,只要最后一次
用户输入内容,获取联想词。但是,每敲一个字就调用接口的话,因为频繁调用接口很浪费资源,所以我们在代码中使用防抖来解决这个问题,只有再用户输入完毕的一段时间后,才会调用接口,出现相对应的数据。
我们只是要拿到猪肉这个关键字然后调取接口去获取联想词,但是就如上面gif显示的一样,我们在输入的过程中就不断调取接口,这十分浪费资源,解决这个问题,我们要采取防抖措施。
let t = null
let inp = document.querySelector('input')
inp.oninput = function () {
if ( t != null ) {
clearInterval(t)
}
t = setTimeout(() => {
// 调取接口(需求)
console.log(this.value)
}, 500);
}
我们引入一个标记t,用这个t来判断我们是否有输入完毕,这段代码的防抖措施就是类似我判断在0.5s内是否还有接着在input框输入,如果有就清除之前的定时器不调取接口,然后重新在生产一个定时器。如果超过0.5秒没有继续输入就认定为输入结束,可以调取接口。
不过呢,这样的话显然 防抖措施和业务所需要的调取接口都写在一起,不利于维护,所以我们简单的封装一下。
let inp = document.querySelector('input')
inp.oninput = debounce(function () {
// 调取接口(需求)
console.log(this.value)
}, 500)
function debounce(callback , delay) {
// 闭包保存标记t
let t = null
return function () {
if ( t != null) {
clearInterval(t)
}
t = setTimeout(() => {
// 修改this指向,不然输出 undefined
callback.call(this)
}, delay);
}
}
节流
- 控制高频事件执行次数,指定时间间隔内只会执行一次任务。
用户在阅读文章的时候,我们需要监听用户滚动到了哪个标题,但是每滚动一下就监听,那样会太过频繁从而占内存,如果再加上其他的业务代码,就卡住了
我们和防抖一样,引入第三个变量flag,让事件在规定时间内指执行一次。下面的节流代码和上面的防抖代码其实是差不多的,这里就不做过多的讲解,直接看效果吧。
let flag = true;
window.onscroll = throttle(function () {
console.log('调取接口')
} , 500)
function throttle(callback , delay) {
// 闭包保存标记flag
let flag = true
return function () {
if (flag) {
setTimeout(() => {
callback.call(this)
flag = true
}, delay);
}
flag = false
}
}
应用场景
防抖:
- 一些表单元素的校验
- 部分搜索功能的联想结果实现
节流:
- 用户点击提交按钮,假设我们知道接口大致的返回时间的情况下,我们使用节流,只允许一定时间内点击一次
- scroll,resize, touchmove, mousemove等极易持续性促发事件的相关动画问题,使用节流按一定时间的频率获取