防抖与节流

防抖

防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。

通俗一点来说,看看下面这个简化的例子:

// 简单的防抖动函数
function debounce(func, wait, immediate) {
    // 定时器变量
    var timeout;
    return function() {
        // 每次触发 scroll handler 时先清除定时器
        clearTimeout(timeout);//清除掉上一次的定时器回调函数,上次事件也就不会执行了。在500ms内,再次滚动,那上次的就清除掉了,不会执行。
        // 指定 xx ms 后触发真正想进行的操作 handler
        timeout = setTimeout(func, wait);
    };
};

// 实际想绑定在 scroll 事件上的 handler
function realFunc(){
    console.log("Success");
}
复制代码

采用了防抖动

window.addEventListener('scroll',debounce(realFunc,500));

封装上面的函数,更简洁

防抖动函数

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, 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);
    };
};

var myEfficientFn = debounce(function() {
    // 滚动中的真正的操作
}, 250);

// 绑定监听
window.addEventListener('resize', myEfficientFn);
复制代码

防抖:

注意:上面的500ms,意思是:两次滚动事件的相隔时间必须大于500ms才能触发成功,而且是倒数第二次的事件触发成功的。如果所有的事件触发的时间间隔都小于500ms,那么就不会触发事件回调函数了,只有最后一次的事件回调能成功执行。
复制代码

节流(Throttling)

  • 防抖函数确实不错,但是也存在问题,譬如图片的懒加载,我希望在下滑过程中图片不断的被加载出来,而不是只有当我停止下滑时候,图片才被加载出来。又或者下滑时候的数据的 ajax 请求加载也是同理。

  • 这个时候,我们希望即使页面在不断被滚动,但是滚动 handler 也可以以一定的频率被触发(譬如 250ms 触发一次),这类场景,就要用到另一种技巧,称为节流函数(throttling)。

  • 节流函数,只允许一个函数在 X 毫秒内执行一次。
  • 与防抖相比,节流函数最主要的不同在于它保证在 X 毫秒内至少执行一次我们希望触发的事件 handler。

  • 与防抖相比,节流函数多了一个 mustRun 属性,代表 mustRun 毫秒内,必然会触发一次 handler ,同样是利用定时器,看看简单的示例:

  	// 简单的节流函数
	function throttle(func, wait, mustRun) {
	    var timeout,
	        startTime = Date.parse(new Date());//重点,这里是在页面加载后就执行的。不是等到滚动才执行。

	        console.log(startTime);

	    return function() {
	        var context = this,
	            args = arguments,
	            curTime = new Date();

	        clearTimeout(timeout);
	        // 如果达到了规定的触发时间间隔,触发 handler
	        if(curTime - startTime >= mustRun){
	            func.apply(context,args);
	            startTime = curTime;//重置开始时间startTime,把它设置成当前的时间
	        // 没达到触发间隔,重新设定定时器
	        }else{
	            timeout = setTimeout(func, wait);
	        }
	    };
	};
	// 实际想绑定在 scroll 事件上的 handler
	function realFunc(){
	    console.log("Success");
	}
	// 采用了节流函数
	window.addEventListener('scroll',throttle(realFunc,500,1000));
复制代码
上面简单的节流函数的例子可以拿到浏览器下试一下,大概功能就是如果在一段时间内 scroll 触发的间隔一直短于 500ms ,那么能保证事件我们希望调用的 handler 至少在 1000ms 内会触发一次。

注意:强调这句话:保证事件我们希望调用的 handler 至少在 1000ms 内会触发一次。最多也是一次。也就是说,在所有滚动事件的每两个相隔时间都加起来,从开始到结束滚动,每隔1000ms就是触发一次。比如从开始到结束,共经历1分钟,每隔1秒调用一次,总共大概调用60次。
复制代码

参考链接:

www.cnblogs.com/fangdongdem…

博客专题里的 github.com/mqyqingfeng…

转载于:https://juejin.im/post/5c6a7b5a6fb9a049fd106648

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值