这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战
前言
前文讲到两种实现版本的节流,这里的高配版本主要将把这两种版本进行优势互补,合并成一个节流函数,通过传参控制具体是要第一时间执行、或者最后一次执行,又或者两者兼得这三种情况
高配节流实现分析
使用时间戳
可以让节流函数立即执行,使用setTimeout
可以让节流函数延迟执行,通过变量控制即可以达到以上需求
通过高配版的节流 ,达到配置以下三种情况:
- 第一次执行,末尾不执行
- 第一次不执行,末尾执行
- 第一次执行,末尾执行
代码实现
<style>
div {
background-color: #666;
height: 300px;
}
</style>
<div></div>
<script>
let dom = document.getElementsByTagName("div")[0];
dom.onmousemove = throttle(listenMoveOn, 200);
function listenMoveOn() {
// 监听的回调做一些事情
}
/**
*
* @param {function} fn - 回调函数
* @param {number} wait - 等待时间
* @param {obejct} options - 配置三种情况
* options = {leading: true, trailing: false}; leading 控制第一次是否执行; trailing 控制最后一次是否执行
*/
function throttle(fn, wait, options) {
/**
*
* @param timer - 定时器
* @param now - 当前时间
* @param context - 保存上下文使用
* @param args - 保存事件参数使用
*/
let timer, now, context, args;
old = 0
// 设置默认情况(第一次执行,最后一次不执行)
if (!options) options = {leading: true, trailing: false}
const later = () => {
// 这里重置old 是为了避免leading、trailing同时为true与时间戳那边相互影响,这一步相当于清除了时间戳那边的操作
old = now
clearTimeout(timer)
timer = null
fn.apply(context, args)
}
return function () {
// 同防抖一样,需要闭包保存相关变量
now = +new Date()
context = this
args = arguments
// 配置 leading 走时间戳管理节流
if (options.leading && now - old > wait) {
// 这里重置定时器 是为了避免leading、trailing同时为true时与定时器那边相互影响,这一步相当于清除了定时器那边的操作
if (timer) {
clearTimeout(timer)
timer = null
}
old = now
fn.apply(context, args)
}
// 配置 trailing 走定时器管理节流
if (options.trailing && !timer) {
timer = setTimeout(later, wait)
}
}
}
</script>
undercore中的throttle
最后还是欣赏一下undercore中的throttle源码
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function (func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function () {
// 定时器方式
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return 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);
}
return result;
};
};
总结
防抖节流已经全部讲完,通过深入学习也算有所收获啦,以前只知道调用没详细了解原理,这回彻底搞懂了 ? 爱了爱了
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!