You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
methods: {// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于getAnswer: _.debounce(function(){if(!reg.test(this.question)){this.answer='Questions usually end with a question mark. ;-)';return;}this.answer='Thinking ... ';letself=this;axios.get('https://yesno.wtf/api')// then中的函数如果不是箭头函数,则需要对this赋值self.then((response)=>{this.answer=_.capitalize(response.data.answer)}).catch((error)=>{this.answer='Error! Could not reach the API. '+error})},500)// 这是我们为判定用户停止输入等待的毫秒数},
[TOC]
DOM操作比起非DOM交互需要更多的内存和CPU时间,连续尝试进行过多的DOM相关操作可能会导致浏览器挂起,有时候甚至会崩溃。
如果在程序中使用了
onresize
事件处理程序,当调整浏览器大小的时候,该事件会连续触发。如果在该事件处理程序内部进行了相关DOM操作,其高频率的更改可能会导致浏览器崩溃。为了绕开这个问题,我们可以考虑使用定时器对该函数进行节流。以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃。
实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理;而其他事件大多的需求是以一定的频率执行后续处理。针对这两种需求就出现了debounce和throttle两种解决办法。
throttle(又称节流)和debounce(又称去抖)其实都是函数调用频率的控制器。
在处理诸如
resize、scroll、mousemove
和keydown/keyup/keypress
等事件的时候,通常我们不希望这些事件太过频繁地触发,尤其是监听程序中涉及到大量的计算或者有非常耗费资源的操作。有多频繁呢?以
mousemove
为例,根据DOM Level 3
的规定,「如果鼠标连续移动,那么浏览器就应该触发多个连续的mousemove
事件」,这意味着浏览器会在其内部计时器允许的情况下,根据用户移动鼠标的速度来触发mousemove
事件。(当然了,如果移动鼠标的速度足够快,比如刷
一下扫过去,浏览器是不会触发这个事件的)。resize、scroll 和 key*
等事件与此类似。1. Debounce(函数防抖)
在
JavaScript
中,debounce
函数所做的事情就是:强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。我们希望在用户停止某个操作一段时间之后才执行相应的监听函数,而不是在用户操作的过程当中,浏览器触发多少次事件,就执行多少次监听函数。比如:在某个
3s
的时间段内连续地移动了鼠标,浏览器可能会触发几十(甚至几百)个mousemove
事件,不使用debounce
的话,监听函数就要执行这么多次;如果对监听函数使用100ms
的去弹跳
,那么浏览器只会执行一次这个监听函数,而且是在第3.1s
的时候执行的。现在,我们就来实现一个 debounce 函数。
1.1 具体实现
更合理的处理方式是:在用户停止输入一小段时间以后,再发送请求。那么
debounce
就派上用场了:2. Throttle(函数节流)
2.1 具体实现
与
debounce
类似,throttle
也接收两个参数,一个实际要执行的函数fn
,一个执行间隔阈值threshhold
。3. debounce和throttle各自的使用场景
3.1 debounce使用场景
第一次触发后,进行倒计wait毫秒,如果倒计时过程中有其他触发,则重置倒计时;否则执行fn。用它来丢弃一些重复的密集操作、活动,直到流量减慢。例如:
3.2 throttle使用场景
第一次触发后先执行fn(当然可以通过{leading: false}来取消),然后wait ms后再次执行,在单位wait毫秒内的所有重复触发都被抛弃。即如果有连续不断的触发,每wait ms执行fn一次。与debounce相同的用例,但是你想保证在一定间隔必须执行的回调函数。例如:
4. 正真的业务场景:
5. debounce和throttle的差异(可视化解释)
6. 项目实例
参考文档
The text was updated successfully, but these errors were encountered: