跳到主要内容

防抖与节流的区别与应用

在前端开发中,我们经常会遇到一些高频触发的事件,如按钮点击、输入框输入、滚动事件等。如果不对这些事件进行优化,可能会导致页面卡顿或者过多的无效请求。这时候就需要用到防抖(Debounce)和节流(Throttle)两种技术。

防抖(Debounce)

概念

防抖指的是如果一个函数持续地被调用,那么只有当函数的调用间隔超过了指定的时间,这个函数才会真正执行。

应用场景

防抖特别适合以下场景:

  1. 实时搜索:当用户在输入框中输入内容时,我们通常希望在用户停止输入后才发送搜索请求,以减少无效的请求。

  2. 表单提交:防止用户快速多次点击提交按钮,导致重复提交表单。

实现示例

下面是一个简单的防抖函数实现:

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)

概念

节流指的是不管函数调用多频繁,都会在指定的时间间隔内只执行一次。

应用场景

节流适合以下场景:

  1. 滚动事件:例如判断用户是否滚动到页面底部来触发无限滚动加载。

  2. 窗口调整:避免在调整窗口大小时频繁触发事件。

  3. 鼠标移动:例如在拖拽元素或者实时追踪鼠标位置时,限制事件触发的频率。

实现示例

下面是一个简单的节流函数实现:

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 毫秒内只会执行一次,避免了频繁触发。