防抖 debounce
应用场景:监听一个输入框,文字变化触发change事件,不使用防抖,每次输入都会触发事件,使用防抖,等用户输入结束或暂停时才触发
<input type="text" class="input"><script>const input = document.querySelector('.input')let timer = nullinput.addEventListener('keyup', () => {if (timer) {window.clearTimeout(timer)}timer = setTimeout(() => {console.log(input.value)timer = null}, 500)})</script>
封装成函数
<input type="text" class="input"><script>const input = document.querySelector('.input')function debounce(fn, delay = 500) {let timer = nullreturn function() {const context = thisif (timer) {window.clearTimeout(timer)}timer = setTimeout(() => {fn.apply(context, arguments)timer = null}, delay)}}input.addEventListener('keyup', debounce(() => { console.log(input.value) }))</script>
节流 throttle
应用场景:拖拽一个元素时,要随时拿到该元素的拖拽位置,如果不想频繁触发导致卡顿,应使用节流,不论拖拽速度有多快,每隔100ms触发一次; 或者监听用户点击按钮,在一定时间内只有1次有效
<div class="div" draggable="true"></div><script>const div = document.querySelector('.div')let timer = nulldiv.addEventListener('drag', (e) => {if (timer) {return}timer = setTimeout(()=> {console.log(e.offsetX, e.offsetY)timer = null}, 100)})</script>
封装成函数
<div class="div" draggable="true"></div><script>const div = document.querySelector('.div')function throttle(fn, delay = 100) {let timer = nullreturn function () {const context = thisif (timer) {return}timer = setTimeout(() => {fn.apply(context, arguments)timer = null}, delay)}}div.addEventListener('drag', throttle((e) => {console.log(e.offsetX, e.offsetY)}))</script>
节流写法二
function throttle(fn, delay=3000) {let canUse = truereturn function() {if (canUse) {canUse = falsefn.apply(this, arguments)window.setTimeout(() => canUse = true, delay)}}}const f = throttle((a) => console.log(a))f(1)f(1) // 不会执行
