节流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;