昌做网站,wordpress博客做seo,烟台网站网站建设,seo基本步骤本文共 2000 字#xff0c;读完只需 8 分钟上一篇文章讲了去抖函数#xff0c;然后这一篇讲同样为了优化性能#xff0c;降低事件处理频率的节流函数。 一、什么是节流#xff1f; 节流函数#xff08;throttle#xff09;就是让事件处理函数#xff08;handler#xf… 本文共 2000 字读完只需 8 分钟 上一篇文章讲了去抖函数然后这一篇讲同样为了优化性能降低事件处理频率的节流函数。 一、什么是节流 节流函数throttle就是让事件处理函数handler在大于等于执行周期时才能执行周期之内不执行即事件一直被触发那么事件将会按每小段固定时间一次的频率执行。 打个比方王者荣耀、英雄联盟、植物大战僵尸游戏中技能的冷却时间技能的冷却过程中是无法使用技能的只能等冷却时间到之后才能执行。 那什么样的场景能用到节流函数呢 比如 页面滚动和改变大小时需要进行业务处理比如判断是否滑到底部然后进行懒加载数据。按钮被高频率地点击时比如游戏和抢购网站。我们通过一个简单的示意来理解 节流函数可以用时间戳和定时器两种方式进行处理。 二、时间戳方式实现 div classcontainer idcontainer正在滑动0
/divscript
window.onload function() {var bodyEl document.getElementsByTagName(body)[0]
}var count 0;
window.onmousemove throttle(eventHandler, 1000);function eventHandler(e) {var containerEl document.getElementById(container);containerEl.innerHTML 正在滑动: count;count;
}function throttle(func, delay) {var delay delay || 1000;var previousDate new Date();var previous previousDate.getTime(); // 初始化一个时间也作为高频率事件判断事件间隔的变量通过闭包进行保存。return function(args) {var context this;var nowDate new Date();var now nowDate.getTime();if (now - previous delay) { // 如果本次触发和上次触发的时间间隔超过设定的时间func.call(context, args); // 就执行事件处理函数 eventHandlerprevious now; // 然后将本次的触发时间作为下次触发事件的参考时间。}}
}
/script 看时间戳实现版本的效果 三、定时器方式实现 div classcontainer idcontainer正在滑动: 0
/divscript
window.onload function() {var bodyEl document.getElementsByTagName(body)[0]
}var count 0;
window.onmousemove throttle(eventHandler, 1000);function eventHandler(e) {var containerEl document.getElementById(container);containerEl.innerHTML 正在滑动: count;count;
}function throttle(func, delay) {var delay delay || 1000;var timer null;return function(args) {var context this;var nowDate new Date();var now nowDate.getTime();if (!timer) {timer setTimeout(function() {func.call(context, args);timer null;}, delay)}}}
/script 看看定时器版实现版本的效果 三、时间戳和定时器的对比分析 对比时间戳和定时器两种方式效果上的区别主要在于 事件戳方式会立即执行定时器会在事件触发后延迟执行而且事件停止触发后还会再延迟执行一次。 具体选择哪种方式取决于使用场景。underscore 把这两类场景用 leading 和 trailing 进行了表示。 四、兼容两种方式, underscore 源码实现 underscore 的源码中就同时实现了时间戳和定时器实现方式在调用时可以自由选择要不要在间隔时间开始时leading执行或是间隔时间结束后trailing执行。 具体看伪代码和示意图 div classcontainer idcontainer正在滑动: 0/divdiv classheight/divscriptwindow.onload function() {var bodyEl document.getElementsByTagName(body)[0]}var count 0;// 事件处理函数function eventHandler(e) {var containerEl document.getElementById(container);containerEl.innerHTML 正在滑动: count;count;}var _throttle function(func, wait, options) {var context, args, result;// 定时器变量默认为 null, 是为了如果想要触发了一次后再延迟执行一次。var timeout null;// 上一次触发事件回调的时间戳。 默认为 0 是为了方便第一次触发默认立即执行var previous 0;// 如果没有传入 options 参数// 则将 options 参数置为空对象if (!options)options {};var later function() {// 如果 options.leading false// 则每次触发回调后将 previous 置为 0, 表示下次事件触发会立即执行事件处理函数// 否则置为当前时间戳previous options.leading false ? 0 : new Date();// 剩余时间跑完执行事件并把定时器变量置为空如果不为空那么剩余时间内是不会执行事件处理函数的见 else if 那。timeout null;result func.apply(context, args);// 剩余时间结束并执行完事件后清理闭包中自由变量的内存垃圾因为不再需要了。if (!timeout)context args null;};// 返回的事件回调函数return function() {// 记录当前时间戳var now new Date();// 第一次执行回调此时 previous 为 0之后 previous 值为上一次时间戳// 并且如果程序设定第一个回调不是立即执行的options.leading false// 则将 previous 值表示上次执行的时间戳设为 now 的时间戳第一次触发时// 表示刚执行过这次就不用执行了if (!previous options.leading false)previous now;// 间隔时间 和 上一次到本次事件触发回调的持续时间的时间差var remaining wait - (now - previous);context this;args arguments;// 如果间隔时间还没跑完则不会执行任何事件处理函数。// 如果超过间隔时间就可以触发方法remaining 0// remaining wait表示客户端系统时间被调整过// 也会立即执行 func 函数if (remaining 0 || remaining wait) {if (timeout) {clearTimeout(timeout);// 解除引用防止内存泄露timeout null;}// 重置前一次触发的时间戳previous now;// result 为事件处理函数(handler)的返回值// 采用 apply 传递类数组对象 argumentsresult func.apply(context, args);// 引用置为空防止内存泄露if (!timeout)context args null;} else if (!timeout options.trailing ! false) {// 如果 remaining 0, 表示在间隔时间内又触发了一次事件// 如果 trailing 为真则会在间隔时间结束时执行一次事件处理函数handler// 在从触发到剩余时间跑完会利用一个定时器执行事件处理函数并在定时器结束时把 定时器变量置为空// 如果剩余事件内已经存在一个定时器则不会进入本 else if 分支, 表示剩余时间已经有一个定时器在运行该定时器会在剩余时间跑完后执行。// 如果 trailing false即不需要在剩余时间跑完执行事件处理函数。// 间隔 remaining milliseconds 后触发 later 方法timeout setTimeout(later, remaining);}// 回调返回值return result;};};window.onmousemove _throttle(eventHandler, 1000);/script 下面是我画的示意图大致总结一下代码对事件处理逻辑的影响 如果 leading 为真那么绿色意味着间隔时间的开始会立即执行第一次触发也会立即执行。如果 trailing 为真那么从蓝紫色的竖细线后的剩余事件会跑一个定时器定时器在时间间隔结束时再执行一次事件处理函数。如果 leading 不为真那么第一次事件触发不会立即执行。如果 trailing 不为真最后一次事件触发后不然再执行一次事件处理函数。节流和去抖的常见场景 输入框打字输入完后才开始异步请求数据校验内容去抖下拉滚动条判断是否到底部进行懒加载数据去抖和节流都可以判断是否到底的方式不同活动网站、游戏网站按钮被疯狂点击节流六、总结 去抖和节流函数都是为了降低高频率事件触发的事件处理频率从而优化网页中大量重绘重排带来的性能问题。 其区别在于去抖会在高频率事件触发时只执行一次节流会在满足间隔时间后执行一次。去抖的 immediate节流中的 leading, trailing 都是为了尽可能满足这类工具函数的不同使用场景。