频繁计算?

之前接到一个需求要把【导航/搜索过滤栏悬浮】改成用户上拉时不展示,下拉并达到一定距离时才展示出来,这类效果在各类APP中都有看到,其中需要计算用户下拉最终停下来时,共下拉了多少px,实现起来也不算太难,就不放代码了。

image

就是这频繁的打印(计算)引发了我的思考,这每秒都在算啊,对性能会不会...,一顿查资料后,发现js性能优化之防抖与节流。

普通情况

<div style="width: 100px;height: 2000px;background-color: skyblue;"></div>

window.onload = function(){
	// 获取滚动条距顶高度
	function getScrollTop() {
	    var scroll_top = 0;
	    if (document.documentElement && document.documentElement.scrollTop) {
	        scroll_top = document.documentElement.scrollTop;
	    }
	    else if (document.body) {
	        scroll_top = document.body.scrollTop;
	    }
	    return scroll_top;
	}
	
	/* 一、普通情况 */
	window.addEventListener('scroll', function(){ console.log(getScrollTop()); });
	/* end */
}

普通情况

RUNOOB 图标

js防抖

防抖是什么?防抖效果img

RUNOOB 图标

概念

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
即:连续触发事件,只执行一次。

例如上图所示,连续触发了滚动事件,但只有最后停下来了,且停下来的时间超过了1s,才执行打印。

/* 二、函数防抖 */
var timeout = null;
function debounce() {
    if(timeout !== null){
        clearTimeout(timeout);  //清除这个定时器
    }

    timeout = setTimeout(function(){
        console.log("防抖 ", getScrollTop());
    }, 1000);
}

window.addEventListener('scroll', function(){
    debounce();
});
/* 函数防抖 end */

所以,我文章开头的频繁计算问题,就可以通过防抖解决。

js节流

节流是什么?节流效果img

RUNOOB 图标

概念

当持续触发事件时,函数会以一定的频率触发。

例如上图所示,一直在触发滚动事件,但打印在以一定的时间间隔出现。

/* 三、函数节流 */
var timer = null;
var throttle = function() {
    if (!timer) {
		timer = setTimeout(function() {
			console.log("节流 ", getScrollTop());
			timer = null;
		}, 1000);
	}
    
}

window.addEventListener('scroll', function(){
	throttle();
});

/* 函数节流 end */

其它场景

当项目中遇到有【高频事件触发】需求的时候,都可以想到节流与防抖。
比如做【搜索联想】时,可以用防抖来节约请求资源,而不是用户输一个字符就请求一次api。
再比如我在做【元素跟随鼠标】时,可以用节流来避免一直计算并设置元素坐标。

正常情况

RUNOOB 图标

加入节流后(每200ms设置一次坐标)

RUNOOB 图标