这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战
前文完整介绍了节流的兄弟:防抖(初始防抖、从underscore库中学习debounce,假设掘友暂时不了解这个,相信从这两篇中掘友定会有所收获),本文开始讲解节流
节流的应用场景:当重复调用函数的时候,至少每隔 wait毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。
节流常见应用场景代表有以下几种:
- dom元素拖拽
- 计算鼠标移动的距离
- 监听scroll滚动
先介绍一下本节实例背景:有一个div,在div上移动触发回调函数
listenMoveOn
,这里使用了简单版本的节流,如下代码所示
第一时间触发,末尾不触发
通过时间戳
实现节流,这种方式会在进入throttle函数中就会立即触发事件监听回调,因为old初始值为0
,now - 0
必定大于wait
,所以这种实现方式 首次肯定会触发,详情请看代码
<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 - 触发间隔时间
*/
function throttle(fn, wait) {
let timer, old, now, context, args;
old = 0
return function() {
now = +new Date()
context = this
args = arguments
if (now - old > wait) { // 因为 now - 0 必定大于wait,所以这种实现方式 首次肯定会触发
fn.apply(context, args)
old = now
}
}
}
</script>
复制代码
第一次不立即触发,末尾触发
使用setTimeout
实现节流,要等到时间达标才会去触发,所以首次不会触发,后面出去之后由于有setTimeout
的存在,所以还会补上一次.
<script>
/**
*
* @param {function} fn - 回调函数
* @param {number} wait - 触发间隔时间
*/
function throttle(fn, wait) {
let timer, context, args;
return function() {
context = this
args = arguments
if (!timer) {
timer = setTimeout(() => {
timer = null // 确保下次进来时能够重新设置定时器
fn.apply(context, args)
}, wait)
}
}
}
</script>
复制代码
小结
本文简单介绍了两种实现节流的方式,这两种方式都各有特色和应用场景,下一节将参考underscore中的throttle进行解析高配版本的节流,综合这两种的优点,达到可以自由控制第一次和末尾是否触发。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END