节流throttle
应用场景
- 滚动事件监听scroll:例如监听页面滚动到底部加载更多数据时,使用节流技术减少检查滚动位置的频率,提高性能。
- 鼠标移动事件mousemove:例如实现一个拖拽功能,使用节流技术减少鼠标移动事件的处理频率。
- 动画效果:当实现一个基于时间的动画效果时,使用节流技术限制动画帧率,降低计算开销。
它使用了闭包和setTimeout来确保函数fn在指定的delay时间内只被调用一次,即使它被频繁触发。这里是对您代码的一个详细解释:
有很多其他的实现方式....比对时间戳
定时器版
function throttle(fn, delay) { // 创建一个标志位canRun,默认为true,表示函数可以被执行 let canRun = true; // 返回一个新的函数,这个函数会包裹原来的fn函数 return function(...args) { // 如果canRun为false,说明上一次fn的执行还没有完成,直接返回不执行 if (!canRun) { return; } // 在函数执行前将canRun设为false,表示fn正在执行或等待执行 canRun = false; // 使用setTimeout来设置一个延时,确保fn在delay时间后执行 // 注意:这里的this和args都是从外部函数捕获的,它们代表了原始事件处理函数的上下文和参数 setTimeout(() => { // 在delay时间后,执行fn函数,并恢复canRun为true,表示可以再次执行fn fn.apply(this, args); canRun = true; }, delay); };
} // 使用示例
const handleScroll = throttle(function() { console.log('Scroll event handled.');
}, 200); // 设置节流间隔为200毫秒 window.addEventListener('scroll', handleScroll);
在这个例子中,handleScroll是节流后的函数,它被用作scroll事件的处理程序。无论用户如何频繁地滚动页面,handleScroll函数都只会每200毫秒执行一次,从而有效地减少了不必要的计算和DOM操作,提高了页面的性能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Throttle Scroll Event Example</title>
<style> /* 为了演示,我们可以添加一些样式使页面更长 */ body { height: 2000px; }
</style>
</head>
<body>
<!-- 为了演示,这里添加一些内容使页面更长 -->
<div style="height: 1000px;">Scroll down to see the throttled scroll event handler in action.</div> <script> // 定义节流函数 function throttle(fn, delay) { let canRun = true; return function(...args) { if (!canRun) { return; } canRun = false; setTimeout(() => { fn.apply(this, args); canRun = true; }, delay); }; } // 定义滚动事件处理函数 function handleScroll() { console.log('Scroll event handled at', new Date().toISOString()); // 这里可以添加实际的滚动处理逻辑,比如加载更多内容、改变样式等 } // 使用节流函数包装滚动事件处理函数 const throttledScrollHandler = throttle(handleScroll, 2000); // 设置节流间隔为200毫秒 // 添加滚动事件监听器 window.addEventListener('scroll', throttledScrollHandler); </script> </body>
</html>
演示
补充:
时间戳版
- 原理:通过比较当前时间和上一次执行函数的时间戳,来判断是否达到指定的时间间隔。
- 示例代码:
function throttle(func, wait) { let previous = 0; return function() { let now = Date.now(); let context = this; let args = arguments; if (now - previous > wait) { func.apply(context, args); previous = now; } }
} // 使用方法
content.onmousemove = throttle(count, 1000); // 每1秒执行一次count函数
使用lodash库
- 示例代码:
html复制代码<script src="./lodash.min.js"></script>
<script> const box = document.querySelector('.box'); let i = 1; function mouseMove() { box.innerHTML = i++; // 如果里面存在大量操作DOM的情况,可能会卡顿 } box.addEventListener('mousemove', _.throttle(mouseMove, 500)); // 每500毫秒执行一次mouseMove函数
</script>
节流防抖的区别
节流throttle指定的delay时间内只被调用一次,即使它被频繁触发;
防抖debounce,只要触发,就重新计算delay;