防抖与节流的区别与应用
在前端开发中,我们经常会遇到一些高频触发的事件,如按钮点击、输入框输入、滚动事件等。如果不对这些事件进行优化,可能会导致页面卡顿或者过多的无效请求。这时候就需要用到防抖(Debounce)和节流(Throttle)两种技术。
防抖(Debounce)
概念
防抖指的是如果一个函数持续地被调用,那么只有当函数的调用间隔超过了指定的时间,这个函数才会真正执行。
应用场景
防抖特别适合以下场景:
-
实时搜索:当用户在输入框中输入内容时,我们通常希望在用户停止输入后才发送搜索请求,以减少无效的请求。
-
表单提交:防止用户快速多次点击提交按钮,导致重复提交表单。
实现示例
下面是一个简单的防抖函数实现:
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
使用示例
<input type="text" id="search" />
<script>
var search = document.getElementById('search');
var doSearch = debounce(function () {
console.log('Searching: ' + this.value);
}, 300);
search.addEventListener('input', doSearch);
</script>
在这个示例中,我们为输入框绑定了一个input
事件,每当用户输入内容时,都会触发doSearch
函数。但是由于使用了防抖,doSearch
函数只会在用户停止输入 300 毫秒后才会真正执行。
节流(Throttle)
概念
节流指的是不管函数调用多频繁,都会在指定的时间间隔内只执行一次。
应用场景
节流适合以下场景:
-
滚动事件:例如判断用户是否滚动到页面底部来触发无限滚动加载。
-
窗口调整:避免在调整窗口大小时频繁触发事件。
-
鼠标移动:例如在拖拽元素或者实时追踪鼠标位置时,限制事件触发的频率。
实现示例
下面是一个简单的节流函数实现:
function throttle(func, wait) {
var context,
args,
timeout,
previous = 0;
var later = function () {
previous = Date.now();
timeout = null;
func.apply(context, args);
};
return function () {
var now = Date.now();
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
};
}
使用示例
<div id="scroll" style="height: 200px; overflow: auto;">
<!-- 大量内容 -->
</div>
<script>
var scroll = document.getElementById('scroll');
var handleScroll = throttle(function () {
if (scroll.scrollTop + scroll.clientHeight >= scroll.scrollHeight) {
console.log('Reached bottom');
}
}, 300);
scroll.addEventListener('scroll', handleScroll);
</script>
在这个示例中,我们为一个滚动容器绑定了scroll
事件,每当用户滚动时都会触发handleScroll
函数。但是由于使用了节流,handleScroll
函数在 300 毫秒内只会执行一次,避免了频繁触发。