是什么?
本质上使用中优化高频率执行代码的一种手段
浏览器的 resize
、scroll
、keypress
、mousemove
等事件在触发时,会高频率的调用绑在事件上的回调函数,极大浪费了资源,降低前端的性能。
对此我们采用节流、防抖来降低事件触发的频率
定义
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
节流
<body>
<button onclick="myclick()">按钮</button>
<button onclick="myclick2()">定时器写法按钮</button>
</body>
<script>
// 时间戳写法
function throttled1(fn, delay = 500){
let startTime=Date.now();
return function(...args){
const nowTime=Date.now();
console.log(nowTime-startTime,delay)
if(nowTime-startTime>=delay){
fn.apply(null,args);
startTime=Date.now();
}
}
}
const myclick=throttled1(()=>{
console.log("事件执行一次");
})
// 定时器的写法
function throttled2(fn, delay = 500) {
let timer = null;
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
}
};
}
const myclick2=throttled2(()=>{
console.log("执行事件一次");
})
</script>
防抖
<script>
function debounce(fn, wait) {
var timer = null;
return function () {
if (timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(fn, wait);
};
}
function handle() {
console.log(Math.random());
}
window.addEventListener("resize", debounce(handle, 1000));
</script>
应用场合:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
- 用户名、手机号、邮箱输入验证;
- 浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。
加强版本的示例
function debounce(func, wait, immediate) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) {
clearTimeout(timer);
};
if (immediate) {
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
// 为空执行
if (callNow){
func.apply(context, args)
}
} else {
timer = setTimeout(function () {
func.apply(context, args);
}, wait);
}
};
}
function handle() {
console.log(Math.random());
}
window.addEventListener("resize",debounce(handle,1000,true)); // 调用立即执行版本
// window.addEventListener("mousemove", debounce(handle, 1000, false)); // 调用非立即执行版本