防抖与节流机制

防抖

/*
	定义一个按钮,并绑定一个点击事件,执行要触发的事件
*/

// 第一步:定义一个按钮
<input type="button" id="btn" value="按钮" />

// 第二步
// 获取标签
var btn = document.getElementById("btn");
// 绑定事件
btn.addEventListener('click', debounce);
// 点击按钮,要触发的事件
function debounce (e) {
	console.log('按钮被点击');
	console.log(e);
}

点击按钮,在控制台打印,发现,一直点击会一直触发事件,如果这个事件为发送一个请求,对服务器来说是不友好的,同样的请求因为用户的多次点击而多次发送请求,返回的数据和只点击一次是一样的,加大的服务器的压力和影响性能,所以,这是我们引入防抖的概念,
简单来说,防抖就是通过setTimeout 的方式,在一定的时间间隔内,将多次触发变成一次触发。

1.通过setTimeout的方式延迟执行

第一种方式为通过设置setTimeout定时器的方式延迟执行,当快速多次点击的时候,每一次都会重置定时器,只有你一段时间都不点击时定时器才能到达条件并执行事件函数。

<input type="button" id="btn" value="按钮" />

var btn = document.getElementById('btn');
// 点击后触发trigger()函数,第一个参数为要执行的函数,第二个参数为定时器延迟时间
btn.addEventListener('click', trigger(debounce, 1000));
function trigger (fn, delay) {
	// 设置time为定时器,初始为null
	var timer = null;
	// 闭包原理,返回一个函数
	return function () {
		// 如果定时器存在清空定时器
		if (timer) {
			clearTimeout(timer);
		}
		// 设置定时器,规定时间后执行真实的函数
		timer = setTimeout (() => {
			// 将参数传递给真实执行的函数,因为箭头函数继承父级作用域,所以直接...arguments
			fn(...arguments);
		}, delay)
	}
}

function debounce (e) {
	console.log('按钮被点击了')
	console.log(e);
}

其中会利用闭包的原理形成作用域,使得定时器不会被下一次点击重复或清空。
运行结果,每次点击都延迟执行。狂点时只有停下后才会执行

2.通过setTimeout的方式第一次会执行,后面不执行

可以发现,第一种方式虽然延迟执行了,但是当用户第一次点的时候也要延迟执行,那就很不友好了。所以下面改进,使得第一次点的时候立即执行,狂点的时候只有第一次有效后面的都没效:

function trigger (fn, delay) {
	var timer = null;
	return function () {
		// 定义一个firstClick,判断是否第一次执行,初始值为true
		var firstClick = !timer;
		// 第一次会立即执行
		if (firstClick) {
			fn(...arguments);
		}
		// 如果定时器存在清空定时器
		if (timer) {
			clearTimeout(timer);
		}
		// 设置定时器,此时firstClick会变为false,规定时间后timer才会变为null
		timer = setTimeout(() => {
			timer = null;
		}, delay);
	}
}

function debounce (e) {
	console.log('按钮被点击了')
	console.log(e);
}

运行结果,第一次点的时候立即执行,狂点的时候只有第一次有效后面的都没效

3.通过setTimeout的方式第一次会执行和最后一次执行

前两个其实就是防抖的经典例子了。这里是扩展知识,继续改进上面案例使得只点击一次的时候立即执行。当点击多次时第一次和最后一次执行。

function trigger (fn, delay) {
	var timer = null;
	return function () {
		var firstClick = !timer;
		if (firstClick) {
			fn(...arguments);
		}
		if (timer) {
			clearTimeout(timer);
		}
		timer = setTimeout (() => {
			timer = null;
			// 如果firstClick为true,执行
			if (!firstClick) {
				fn(...arguments);
			}
		}, delay);
	}
}

function debounce (e) {
	console.log('按钮被点击了')
	console.log(e);
}

运行结果,只点击一次的时候立即执行。当点击多次时第一次和最后一次执行。

节流

简单来说,就是你一直狂点不停的话,它会每隔一定时间就执行一次。它与防抖最大的区别就是,无论事件触发多么频繁,都可以保证在规定时间内可以执行一次执行函数

利用时间戳实现

btn.addEventListener("click", trigger(debounce, 500));

function trigger (fn, delay) {
	// 设置previous,为上一次执行时间,初始为0
	var previousTime = 0;
	return function () {
		// 获取当前时间戳
		var now = new Date().getTime();
		// 如果当前时间减去上次时间大于限制时间时才执行
		if (now - previousTime > delay) {
			// 执行函数
			fn(...arguments);
			// 执行后,上次时间赋值为这次执行时间
			previous = now;
		}
	}
}

function debounce (e) {
	console.log('按钮被点击了')
	console.log(e);
}

运行结果,一点就运行。狂点不停的话,每隔500毫秒才执行一次。

利用定时器实现

function trigger (fn, delay) {
	// flag 为true
	var flag = true;
	return function () {
		// 如果flag为true执行定时器
		if (flag) {
			setTimeout(() => {
				// 到规定时间后执行函数,同时flag = true
				fn(...arguments);
				flag = true;
			}, delay);
		}
		// flag = false; 防止一直执行
		flag = false;
	}
}

三.总结:
  防抖就是通过setTimeout 的方式,在一定的时间间隔内,将多次触发变成一次触发 。节流:就是减少一段时间的触发频率。防抖与节流最大的区别就是,无论事件触发多么频繁,都可以保证在规定时间内可以执行一次执行函数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值