防抖
定义 : n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时。
场景:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
实现
bash
const debounce = (fn,timeout)=>{
let timer = null;
return function(...arg){
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this,arg)
}, timeout);
}
节流
定义 : n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
场景:
- 滚动加载,加载更多或滚到底部监听
- 搜索框,搜索联想功能
实现
bash
function throttle(fn,time) {
let timer = null;
return function(...arg) {
if (timer) { return }
timer = setTimeout(() => {
fn.apply(this,arg)
timer = null
}, time)
}
}
防抖节流函数中的this和参数问题
bash
import React, { useState } from 'react';
import './App.css';
function App() {
const obj = {a : 1};
function throttle(fn,time) {
let timer = null;
//这里throttle返回的函数之所以用非箭头函数,是为了可以将它的this绑在一个对象上, 如下面的obj.final,就是把返回的函数绑在了obj上, 而fn用apply也会将this指向指定的执行环境
return function(...arg) { //剩余参数语法会将函数内的所有剩余实参转换成一个数组,这里接受到的就是888
console.log('this222',this) //this: obj
if (timer) { return }
timer = setTimeout(() => {
console.log('this333',this) //这里的this是用的最近一个非箭头函数的this
fn.apply(this,arg) // arg是一个数组,直接作为apply的参数即可
timer = null
}, time)
}
}
function myFn(aaa){
console.log(this, aaa) //this: obj ,aaa: 888
}
obj.final= throttle(myFn,1000) //为了给这个myFn传参,得先在外面得到这个被节流的函数
return (
<div className="App" onClick={() => {obj.final('888')}}>
<div className="wrap">
</div>
</div>
);
}
export default App;
参考文章:
https://zhaocchen.github.io/docs/whiteboard/throttle-debounce/