什么是节流
节流是限制事件触发的频率,当持续触发事件时,在一定时间内只执行一次事件,这个效果跟英雄联盟里的闪现技能释放差不多。
函数防抖关注一定时间连续触发的事件只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>节流</title> <script src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script> </head> <body> <div> 普通输入框: <input class="input1" /> </div> <div> 节流输入框: <input class="input2" /> </div> <script> // 普通 const inputEl1 = document.querySelector(".input1"); let counter1 = 1; inputEl1.oninput = function () { console.log(`发送网络请求${counter1++}`, this.value); }; // 节流处理过的 const inputEl2 = document.querySelector(".input2"); let counter2 = 1; inputEl2.oninput = _.throttle(function () { console.log(`节流处理:发送网络请求${counter2++}`, this.value); }, 1000); </script> </body> </html>
手写 throttle
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>手写节流</title> <script> // 时间戳实现节流 function kaimoThrottle(fn, delay) { let startTime = 0; let _throttle = function (...args) { let now = new Date().getTime(); let waitTime = delay - (now - startTime); if (waitTime <= 0) { fn.apply(this, args); startTime = now; } } return _throttle; } // setTimeout 实现节流 function kaimoThrottle2(fn, delay) { let timer = null; let _throttle = function (...args) { // 如果 timer 不为 null,说明上一个定时器还未执行,则直接返回 if (timer) { return; } // 开启新的一个定时器 timer = setTimeout(() => { // this 和参数绑定 fn.apply(this, args); // 函数执行完之后,将timer置为null timer = null; }, delay); }; return _throttle; } </script> </head> <body> <div> 节流输入框: <input class="input" /> </div> <script> const inputEl = document.querySelector(".input"); let counter = 1; inputEl.oninput = kaimoThrottle2(function (e) { console.log(`手写节流:发送网络请求${counter++}`, this, this.value); console.log(e); }, 1000); </script> </body> </html>