防抖策略(debounce):当事件被触发后,延迟 n 秒后再执行回调,;若在n秒内又被触发,则重新计时。
多次触发只执行一次,比如王者荣耀回城,只有经过8秒才能触发回城,8秒途中再次触发回城或中断,都需要重新等待8秒才能回城
登录、发短信等按钮避免用户点击太快,导致发送了多次请求,需要防抖。
let debounce = function (handler,delay) {
let timer=null;
return function () {
if(timer) clearTimeout(timer);
timer = setTimeout(()=>{
fn.apply(this,arguments)
},delay)
}
}
在规定的时间范围内不会重复触发回调,只有大于这个时间间隔才会触发,把频繁触发变为少量触发。
一个周期只执行一次,比如王者荣耀技能,只有经过技能冷却时间,,才能再次使用
① 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
② 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源;
③ 浏览器input搜索框展示下拉列表,需要节流,也可以使用防抖
let throttle = function(handler,delay) {
let timer = null;
return function () {
if(timer) return;
timer = setTimeout(() => {
fn.apply(this,arguments)
timer = null
})
}
}
名称 | 区别 | 举例 |
---|---|---|
防抖 | 最后一次执行的是防抖 | 王者荣耀回城技能 |
节流 | 控制次数的是节流 | 英雄cd技能 |
通过对比防抖和节流函数,可以发现两者一个是return,一个是clearTimeout,为什么?
答:
防抖是触发间隔大于timer才会触发,所以每次在小于间隔time要清除定时器;
节流是不管time内触发多少次,只会每间隔time时间才会触发一次,所以用return
总结:防抖是限制操作,节流是减少操作
如果你在1秒内输入123,那它就会在1秒内分别执行输入1、2、3时的事件。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>正常案例title>
head>
<body>
<input type="text" id="input">
<script>
let input = document.getElementById("input");
let span = document.createElement('span');
let num = 0;
input.addEventListener("input", inputEvent)
//输入事件
function inputEvent(e) {
console.log(e, this)
num++;//记录请求次数
span.innerHTML = `第
${num}次请求了接口`;
document.body.appendChild(span);
}
script>
body>
html>
如果在200ms内输入123,那它只会执行输入3时的事件。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>防抖title>
head>
<body>
<input type="text" id="input">
<script>
let input = document.getElementById("input");
let span = document.createElement('span');
let num = 0;
input.addEventListener("input", debounce(inputEvent, 200))
//输入事件
function inputEvent(e) {
console.log(e, this)
num++;//记录请求次数
span.innerHTML = `第
${num}次请求了接口`;
document.body.appendChild(span);
}
//防抖
function debounce(fn, delay) {
//这里相当于定义了一个全局的timer
let timer = null;
return function () {
//如果定时器存在,那就清掉,开启新的计时器
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
}
script>
body>
html>
如果你在一秒内输入123,那它只会执行输入1时的方法。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>节流title>
head>
<body>
<input type="text" id="input">
<script>
let input = document.getElementById("input");
let span = document.createElement('span');
let num = 0;
input.addEventListener("input", throttle(inputEvent, 1000))
//输入事件
function inputEvent(e) {
console.log(e, this)
num++;//记录请求次数
span.innerHTML = `第
${num}次请求了接口`;
document.body.appendChild(span);
}
//节流
function throttle(fn, delay) {
//相当于在全局定义了一个timer
let timer = null;
return function () {
//如果timer存在,直接结束函数
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments);
//指定时间结束后,将timer变成null,否则这个函数将一直不执行
timer = null
}, delay);
}
}
script>
body>
html>
第三方插件库:lodash
地址:https://www.lodashjs.com/