节流&&防抖

152 阅读3分钟

相信这两个概念你肯定听过,这里我们来深入剖析一下,什么是节流,什么又是防抖。

说起来节流和防抖的目的都是一样的,优化浏览器性能,降低资源浪费,只是实现的方式是不同的,所造成的效果也是不同的。我们来仔细看看两者的区别吧。

节流(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来判断;

这些就是两者的主要区别了。

入坑新手,若文中有错误的地方望多多指正,不要客气