We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
上一篇文章我们已经学习了防抖的实现原理,如果还没有学习的同学可以戳这里学习。今天我们一起来学习节流的实现原理。
如果你在这 1s 内连续触发事件,那么只执行一次。(1s 为自定义间隔时间)
这里有首次是否执行和结束后是否执行两种效果,而它们的实现方式也各有不同。
好,看完上面对节流的概述,我们可以简单实现如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1"> <title>throttle</title> <style> #wrapper { width: 100%; height: 200px; line-height: 200px; text-align: center; font-size: 30px; color: #fff; background-color: #666; } </style> </head> <body> <div id="wrapper"></div> <script src="throttle.js"></script> </body> </html>
// throttle.js let count = 1 let wrapperDom = document.getElementById('wrapper') function doEvent (e) { wrapperDom.innerHTML = count++ } function throttle (func, wait) { let timerId let lastInvokeTime = 0 function throttled (...args) { const lastThis = this const lastArgs = args if (!timerId) { timerId = setTimeout(function () { timerId = null func.apply(lastThis, lastArgs) }, wait) } } return throttled } wrapperDom.onmousemove = throttle(doEvent, 1500)
运行效果图如下:
从效果图可以看出,鼠标首次触发事件是在 1.5s 后,就是说它不是立即触发事件的,而且在鼠标移出区域 1.5s 后,即结束后执行了一次事件。
我现在想让它首次执行事件该如何修改代码呢?见下方实现:
function throttle (func, wait) { let lastInvokeTime = 0 function throttled (...args) { const lastThis = this const lastArgs = args const time = Date.now() if (time - lastInvokeTime > wait) { func.apply(lastThis, lastArgs) lastInvokeTime = time } } return throttled }
从该效果图可以看出,它与上面介绍的有两点不同:1、首次执行事件;2、结束后没有执行事件。
现在将上面两种效果结合,且外部可以通过传递参数控制首次或结束是否执行事件。我们定下规则:
function throttle (func, wait, options) { let timerId, lastThis, lastArgs, result let lastInvokeTime = 0 let leading = true let trailing = true if (options) { leading = 'leading' in options ? !!options.leading : leading trailing = 'trailing' in options ? !!options.trailing : trailing } function throttled (...args) { const time = Date.now() lastThis = this lastArgs = args if (!lastInvokeTime && !leading) { lastInvokeTime = time } const remainingWait = wait - (time - lastInvokeTime) // 如果没有剩余的时间了或者你改了系统时间 if (remainingWait <= 0 || remainingWait > wait) { if (timerId) { clearTimeout(timerId) timerId = null } lastInvokeTime = time result = func.apply(lastThis, lastArgs) if (!timerId) { lastThis = lastArgs = null } } else if (!timerId && trailing) { // leading 和 trailing 的值不允许同时为 false timerId = setTimeout(invokeFunc, remainingWait) } return result } function invokeFunc () { lastInvokeTime = leading ? 0 : Date.now() timerId = null result = func.apply(lastThis, lastArgs) if (!timerId) { lastThis = lastArgs = null } } // 取消 function cancel () { lastInvokeTime = 0 timerId = null clearTimeout(timeout) } throttled.cancel = cancel return throttled } wrapperDom.onmousemove = throttle(doEvent, 1500, { trailing: false }) // wrapperDom.onmousemove = throttle(doEvent, 1500, { // leading: false // })
本文到这里就结束了,通过文章我们了解到什么是节流以及它的实现原理,使用节流函数可以解决项目中,懒加载要监听计算滚动条的位置,按一定时间的频率获取。
在前端面试中,节流函数还是一道高频考题,希望小伙伴们看完本文后能够顺利拿下。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
阅读 lodash 源码学节流
前言
上一篇文章我们已经学习了防抖的实现原理,如果还没有学习的同学可以戳这里学习。今天我们一起来学习节流的实现原理。
介绍
如果你在这 1s 内连续触发事件,那么只执行一次。(1s 为自定义间隔时间)
这里有首次是否执行和结束后是否执行两种效果,而它们的实现方式也各有不同。
实现
好,看完上面对节流的概述,我们可以简单实现如下:
运行效果图如下:
从效果图可以看出,鼠标首次触发事件是在 1.5s 后,就是说它不是立即触发事件的,而且在鼠标移出区域 1.5s 后,即结束后执行了一次事件。
我现在想让它首次执行事件该如何修改代码呢?见下方实现:
运行效果图如下:
从该效果图可以看出,它与上面介绍的有两点不同:1、首次执行事件;2、结束后没有执行事件。
优化
现在将上面两种效果结合,且外部可以通过传递参数控制首次或结束是否执行事件。我们定下规则:
运行效果图如下:
结语
本文到这里就结束了,通过文章我们了解到什么是节流以及它的实现原理,使用节流函数可以解决项目中,懒加载要监听计算滚动条的位置,按一定时间的频率获取。
在前端面试中,节流函数还是一道高频考题,希望小伙伴们看完本文后能够顺利拿下。
参考文献
The text was updated successfully, but these errors were encountered: