相信这两个概念你肯定听过,这里我们来深入剖析一下,什么是节流,什么又是防抖。
说起来节流和防抖的目的都是一样的,优化浏览器性能,降低资源浪费,只是实现的方式是不同的,所造成的效果也是不同的。我们来仔细看看两者的区别吧。
节流(throttle)
节流最简单的理解就是给方法加上CD(冷却),一段时间只能触发一次,这就是节流
比如监听滚动事件,
let x = 0;
window.addEventListener('scroll', function () {
console.log("我滚动了",x++ )
})
这是不使用节流的效果,稍微滚动一点,触发N次事件,接下来初步使用节流
使用节流以后效果:
节流可通过两种方式实现,时间戳的和定时器
-
时间戳实现:
-
简单处理(除了复用性,没别的问题)
let x = 0; let prev = 0; const delay = 300; window.addEventListener('scroll',() => { let now = Date.now(); if (now - prev >= delay) { console.log("我滚动了", x++) prev = now; } }) -
封装(封装成一个公用方法,可复用)
let x = 0 let prev = 0; let log = function() { console.log(x++); } let throttle = function(func, delay) { return function() { const context = this; let args = arguments; let now = Date.now(); if (now - prev >= delay) { func.apply(context, args); prev = now; } } } window.addEventListener('scroll', throttle(log, 300));
定时器实现:
-
简单处理
let x = 0; let timer = null; window.addEventListener('scroll', function() { if (!timer) { timer = setTimeout(() => { console.log("我滚动了", x++) timer = null; }, 300) } }) -
封装(封装成一个公用方法,可复用)
let x = 0; let log = function() { console.log(x++); } let throttle = function(func, delay) { let timer = null; return function() { const context = this; let args = arguments; if (!timer) { timer = setTimeout(() => { func.apply(context, args); timer = null; },delay) } } } window.addEventListener('scroll', throttle(log, 300))
这两种实现方式的区别在于,时间戳节流函数会在第一次触发事件时立即执行,以后每过 delay 秒之后才执行一次,但是最后一次触发事件不会被执行;定时器节流函数则是第一次触发时不会执行,在 delay 秒之后执行,当最后一次停止触发后,还会再执行一次函数。
防抖(debounce)
防抖简单理解就是最后一个人说的算,短时间内多次触发,只执行最后一次
比如输入联想,用户在输入框输入有联想提示,但是如果每个字符都请求就很浪费资源,这时候就是使用防抖了,
首先是不使用防抖的效果
使用防抖处理后
不使用防抖的代码
<body>
<input type="text" id="ot" />
</body>
<script>
let x = 0
let ot = document.getElementById("ot")
function log () {
console.log(x++)
}
ot.addEventListener('input',log)
</script>
防抖简单使用
let x = 0;
let timer = null;
let ot = document.getElementById("ot")
function log() {
console.log(x++)
}
ot.addEventListener('input', () => {
if (!timer) {
clearTimeout(timer);
timer = setTimeout(function() {
log();
}, 1000)
}
})
封装复用
let x = 0
let ot = document.getElementById("ot")
function log () {
console.log(x++)
}
// 接受一个需要防抖的函数和延迟执行的时间作为参数
function debounce(fn, delay){
// 设置一个 timer
let timer = null;
return function() {
// 获取函数的作用域和变量
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context, args);
}, delay)
}
}
ot.addEventListener('input',debounce(log,1000))
每一次事件被触发,都会清除当前的 timer 然后重新设置超时调用。只有在最后一次触发事件,才能在 delay 时间后执行。
两者的主要应用场景
防抖:
1、search搜索联想,用户在不断输入值时,用防抖来节约请求资源;
2、用户多次点击提交,防止表单重复提交;
节流:
1、监听滚动事件,比如懒加载时要监听计算滚动条的位置,用throttle来判断;
这些就是两者的主要区别了。
入坑新手,若文中有错误的地方望多多指正,不要客气