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
要实现一个xxx函数,首先要明白这个函数的意思,然后思考一些,需要接受的参数,以及需要返回什么
防抖:不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。
思路:
需要注意问题:
function debounce(fn, wait, immediate) { let timer = null; // 返回一个函数 return function(...args) { // 每次触发事件时都取消之前的定时器 clearTimeout(timer); // 判断是否要立即执行一次 if(immediate && !timer) { fn.apply(this, args); } // setTimeout中使用箭头函数,就是让 this指向 返回的该闭包函数,而不是 debounce函数的调用者 timer = setTimeout(() => { fn.apply(this, args) }, wait) } }
通过闭包保存一个标记(timer)来保存setTimeout返回的值, 每当要触发函数的时候, 需要先把上一个setTimeout清除掉, 然后再创建一个新的setTimeout, 这样就能保证执行函数后的 wait 间隔内如果还要触发函数, 就不会执行fn
window.addEventListener('resize', debounce(handleResize, 200)); window.addEventListener('scroll', debounce(handleScroll, 200));
window 的 resize、scroll, mousedown、mousemove, keyup、keydown等高频触发的事件
debounce(fetchSearchData, 200);
可以这样去理解记忆:函数防抖是 在事件触发 n 秒后才执行,在监听 scroll事件和 resize 事件时,只要 n 秒后才执行一次就可以了,不需要每次只要一触发 scroll或 resize的时候就执行,n秒内的执行是没有意义的(用户可能都感受不到,而且很容易造成卡顿)。
scroll
resize
函数节流:不管事件触发频率有多高,只在单位时间内执行一次。 简单分析一下我们要实现的函数的一些信息
有两种思路实现: 使用时间戳和定时器
function throttle(fn, wait) { // 记录上一次执行的时间戳 let previous = 0; return function(...args) { // 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔,就执行函数,否则不执行 if(Date.now() - previous > wait) { // 更新上一次的时间戳为当前时间戳 previous = Date.now(); fn.apply(this, args); } } }
第一次事件肯定触发,最后一次不会触发(比如说监听 onmousemove,则鼠标停止移动时,立即停止触发事件)
function throttle(fn, wait) { // 设置一个定时器 let timer = null; return function(...args) { // 判断如果定时器不存在就执行,存在则不执行 if(!timer) { // 设置下一个定时器 timer = setTimeout(() => { // 然后执行函数,清空定时器 timer = null; fn.apply(this, args) }, wait) } } }
第一次事件不会触发(fn是放在 setTimeout中执行的,所以第一次触发事件至少等待 wait 毫秒之后才执行),最后一次一定触发
两者结合可以实现,第一次事件会触发,最后一次事件也会触发
function throttle(fn, wait) { // 记录上一次执行的时间戳 let previous = 0; // 设置一个定时器 let timer = null; return function(...args) { // 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔 if(Date.now() - previous > wait) { clearTimeout(timer); timer = null // 更新上一次的时间戳为当前时间戳 previous = Date.now(); fn.apply(this, args); } else if(!timer) { // 设置下一个定时器 timer = setTimeout(() => { timer = null; fn.apply(this, args) }, wait) } } }
比较节流和防抖的可视化界面
The text was updated successfully, but these errors were encountered:
以前实现函数节流的方法时没有考虑过回调函数首次、末尾是否执行的情况,这次受用了,支持一下!
Sorry, something went wrong.
No branches or pull requests
函数防抖(debounce)
防抖:不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。
思路:
需要注意问题:
通过闭包保存一个标记(timer)来保存setTimeout返回的值, 每当要触发函数的时候, 需要先把上一个setTimeout清除掉, 然后再创建一个新的setTimeout, 这样就能保证执行函数后的 wait 间隔内如果还要触发函数, 就不会执行fn
使用场景
window 的 resize、scroll, mousedown、mousemove, keyup、keydown等高频触发的事件
可以这样去理解记忆:函数防抖是 在事件触发 n 秒后才执行,在监听 scroll事件和 resize 事件时,只要 n 秒后才执行一次就可以了,不需要每次只要一触发
scroll
或resize
的时候就执行,n秒内的执行是没有意义的(用户可能都感受不到,而且很容易造成卡顿)。函数节流(throttle)
函数节流:不管事件触发频率有多高,只在单位时间内执行一次。
简单分析一下我们要实现的函数的一些信息
有两种思路实现: 使用时间戳和定时器
使用时间戳
第一次事件肯定触发,最后一次不会触发(比如说监听 onmousemove,则鼠标停止移动时,立即停止触发事件)
使用定时器
第一次事件不会触发(fn是放在 setTimeout中执行的,所以第一次触发事件至少等待 wait 毫秒之后才执行),最后一次一定触发
定时器和时间戳结合
两者结合可以实现,第一次事件会触发,最后一次事件也会触发
比较节流和防抖的可视化界面
参考
The text was updated successfully, but these errors were encountered: