节流和防抖在前端性能优化方面具有举足轻重的作用。看过八股或者参加过面试的同学想必不用多说,都知道这-是个经常考察的内容。
什么是防抖:
防抖就是连续触发事件时只执行一次。比如连续点击表单提交按钮。如果不做防抖优化,会重复提交给服务端造成不小压力,如果是脚本的恶意进攻,危害不言而喻。如果做了防抖优化,在连续的事件中,仅仅触发一次。
那么如何实现防抖?
实现思路:
事件在触发一段时间后执行,如果在这段时间内再次触发,则重新计时。
<body>
<button class="debounceBtn">防抖</button>
<script>
const debounceBtn = document.querySelector('.debounceBtn');
function logger () {
console.log('点击了一次');
}
debounceBtn.addEventListener('click', debounce(logger, 1000));
function debounce (fn, delay) {
let timer = null;
return function () {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay)
}
}
</script>
</body>
什么是节流?
听名字,节流就感觉和防抖不一样,防抖是无论如何都只执行一次,多少显得寒酸?节流,节省资源,节能限流。我不管你点了多久,我只在规定时间内执行一次。你点击60秒,我规定5秒执行一次,那就执行12次。
事件在固定时间间隔内最多执行一次,无论期间触发多少次。
实现思路:
初始时设置上次执行时间为0,第一次触发的时候,获取触发时间,如果(触发时间-上次触发时间)> 限制时间。就执行一次,并且更改上次触发时间,把这次触发时间赋值给上次触发时间,给下次触发使用。
<body>
<!-- 节流:一段时间内执行一次 -->
<button class="throttleBtn">节流</button>
<script>
const throttleBtn = document.querySelector('.throttleBtn');
function logger(className) {
console.log(`按钮${className}被点击了。`)
}
throttleBtn.addEventListener('click', throttle(logger, 1000))
function throttle(func, wait) {
let previous = 0 // 上一次执行的时间
return function () {
let now = Date.now()
if(now - previous > wait) {
func.apply(this, arguments)
previous = now
}
}
}
</script>
</body>
应用场景:
防抖:无论连续多少次,只触发一次
表单提交:
- 用户可能会在短时间内多次点击提交按钮,导致表单被多次提交。通过防抖机制,可以确保表单在一定时间内只被提交一次。
搜索框输入:
- 在搜索框中输入文字时,每输入一个字符都会触发搜索请求,这会导致大量不必要的请求。通过防抖机制,可以在用户停止输入一定时间后再发送请求,从而减少请求次数。
窗口大小调整:
- 在调整浏览器窗口大小时,会触发大量的 resize 事件。通过防抖机制,可以在用户停止调整窗口大小一定时间后,再执行相关操作。
节流:节能限流,一段时间执行一次
滚动事件:
- 当用户滚动页面时,频繁触发 scroll 事件会导致性能问题。通过节流,可以限制处理 scroll 事件的频率,比如每隔 200 毫秒处理一次,从而提升页面的性能。
窗口大小调整:
- 当用户调整浏览器窗口大小时,频繁触发 resize 事件。通过节流,可以限制处理 resize 事件的频率,避免性能问题。
输入框输入:
- 在文本输入框中输入时,频繁触发 input 事件。通过节流,可以限制处理 input 事件的频率,减少不必要的处理。
鼠标移动:
- 处理鼠标移动事件(如绘图应用)时,可以通过节流限制处理 mousemove 事件的频率,从而减少计算量和提高性能。
API 请求:
- 在某些场景下,需要频繁发送 API 请求,比如实时搜索或数据同步。通过节流,可以限制请求的频率,避免服务器过载。