前言
在前端开发的过程中,我们经常会需要绑定一些持续触发事件,如窗口的resize、scroll,输入框内容校验等等,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕,这时候就要用到防抖(debounce)和节流(throttle),减少调用频率的同时又不影响实际效果。
函数防抖(debounce)
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
简单来说就是,任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
防抖函数分为非立即执行版和立即执行版。
函数防抖实现
1、非立即执行版
<input type="text" placeholder="防抖非立即执行" id="debounceInput1">
<script>
function debounce1(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
//监听input的输入事件
$('#debounceInput1').on('input propertychange',debounce1(function(){
console.log($(this).val(),new Date())
},1000));
</script>
2、立即执行版
<input type="text" placeholder="防抖立即执行" id="debounceInput2">
<script>
function debounce2(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
//监听input的输入事件
$('#debounceInput2').on('input propertychange',debounce2(function(){
console.log($(this).val(),new Date())
},1000));
</script>
函数防抖应用场景
1、搜索框输入查询,若用户一直在输入中,没有必要不停的去请求服务端接口,设置一个合适的时间间隔,能有效减轻服务端压力。
2、按钮提交事件,防止短时间内重复提交。
3、浏览器窗口resize事件,不断调整浏览器窗口大小时会触发这个事件,利用防抖来让其触发一次重新计算布局。
函数节流(throttle)
当持续触发事件时,保证一定事件段内只调用一次事件处理函数。
简单来说就是,连续触发事件但在n秒中只执行一次函数,节流会稀释函数的执行频率。
节流函数有两种实现方法,时间戳和定时器。
函数节流实现
1、时间戳
<button id="btn1">点击(时间戳)</button>
<script>
function throttle1(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;
}
}
}
$('#btn1').on('click',throttle1(function(){
console.log("时间戳",new Date())
},1000));
</script>
2、定时器
<button id="btn2">点击(定时器)</button>
<script>
function throttle2(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
$('#btn2').on('click',throttle2(function(){
console.log("定时器",new Date())
},1000));
</script>
函数节流应用场景
1、鼠标不断触发mousedown或者mouseover事件的时候,可以利用节流在单位时间内只触发一次。
2、监听滚动事(onScoll),比如是否滑到底部加载更多数据,用节流来判断。
3、按钮点击事件。
区别
函数防抖:事件高频触发后,间隔 n 秒执行一次。
函数节流:事件高频触发中,每 n 秒执行一次。
节流函数的回调执行时机是在高频触发中,而防抖函数的回调函数执行时机是在高频触发后。
注意: 函数防抖和函数节流只是减少了事件回调函数的执行次数,并不会减少事件的触发频率。