最近本身撸了一个轮播图,在点击切换的时候,为了寻求更好的用户体验,引入了节流,在此记录对源码的学习过程
源码来源:underscorehtml
函数防抖(debounce)
使用场景:如今咱们须要作一个搜索框,当用户输入文字,执行keyup事件的时候,须要发出异步请求去进行结果查询。但若是用户快速输入了一连串字符,例如是5个字符,那么此时会瞬间触发5次请求,这确定不是咱们但愿的结果。咱们想要的是用户中止输入的时候才去触发查询的请求,这个时候函数防抖能够帮到咱们
原理:让函数在上次执行后,知足等待某个时间内再也不触发次函数后再执行,若是触发则等待时间从新计算git
function debounce (func, wait, immediate) { var timeout, result; var later = function (context, args) { timeout = null;//重置 if (args) result = func.apply(context, args); }; var debounced = restArguments(function (args) { if (timeout) clearTimeout(timeout);//若是触发则等待时间从新计算 if (immediate) {//应用场景,好比提交表单,须要当即执行一次 var callNow = !timeout;//是否为第一次触发,若是是第一次触发,timeout是undefined timeout = setTimeout(later, wait);//注意,这里没有args,仅仅只是在wait毫秒后重置清空timeout, if (callNow) result = func.apply(this, args);//若是是immediate且是第一次触发,当即执行一次;result为当即执行的结果,这里this直接绑定到用户的func } else { timeout = delay(later, wait, this, args);//settimeout,注意:这里的this经过参数传给later绑定到func } return result; }); //重置,取消执行 debounced.cancel = function () { clearTimeout(timeout); timeout = null; }; return debounced; };
函数节流(throttle)
使用场景:window.onscroll,以及window.onresize等,每间隔某个时间去执行某函数,避免函数的过多执行
原理:与函数防抖不一样,它不是要在每完成某个等待时间后去执行某个函数,而是要每间隔某个时间去执行某个函数github
// leading:是否当即执行 // trailing: true // wait期间若是再次调用,是否会在周期后边缘(wait刚结束)再次执行 //leading = true;trailing = true; 调用当即执行一次,wait期间若是再次调用,会在周期后边缘(wait刚结束)再次执行 //leading = true;trailing = false; 调用当即执行一次,wait期间若是再次调用,什么也不作 //leading = false;trailing = true; 调用需等待wait时间,wait期间若是再次调用,会在周期后边缘(wait刚结束)执行 //leading = false;trailing = false; 调用需等待wait时间,wait期间若是再次调用,什么也不作 function throttle (func, wait, options) { var timeout, context, args, result; var previous = 0;//上次执行时间 if (!options) options = {}; var later = function () { previous = options.leading === false ? 0 : _.now();//设置为0的话下次调用会当即执行 timeout = null; result = func.apply(context, args);//可能设置timeout? if (!timeout) context = args = null; }; var throttled = function () { var now = _.now(); if (!previous && options.leading === false) previous = now;//若是不是当即执行 var remaining = wait - (now - previous);//剩余时间 context = this; args = arguments; if (remaining <= 0 || remaining > wait) {//开始执行 if (timeout) { clearTimeout(timeout); timeout = null; } previous = now;//记录执行时间 result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining);//注意只有这个地方对timeout赋值了且调用了later } return result; }; //取消 throttled.cancel = function () { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled; };
全部学习过程可见注释,完整注释GitHub地址
其中我在造轮播图的轮子的过程当中,引入了节流来优化用户主动点击切换,一次来提高用户体验,感受上仍是好不少的。
轮播图演示地址app