一、什么是防抖和节流?为什么用?
|--引入防抖和节流解决的问题:当一个函数被频繁、无限制的被调用的时候,会加重浏览器的负担,造成浏览器卡顿的现象。例如:常用浏览器滚动scroll,鼠标移动onmousemove事件触发的事件。因此引入了防抖和节流两个概念来解决这个问题。
|--防抖:当持续触发事件时,指定时间(自定义)没有再触发事件,事件处理函数才会执行一次。如果小于指定。时间触发事件,事件处理函数不会被执行,而是以最后一次触发的事件,重新计算,即:最后时间点后指定时间,触发事件。通俗理解:停止动作后(时间点)+ 自定义时间(延迟)=> 触发事件
|--节流:当持续触发事件时,每隔指定时间触发一次事件处理函数。当然,是你触发事件的时间小于你设置的
每隔指定时间。通俗解决:“匀速等距离”触发事件处理函数。
二、防抖(debounce)
|--案例:onmousemove鼠标移动触发事件处理函数。
|--解决方案:通过防抖函数
|--封装防抖函数分析:防抖即当我停止操作(鼠标移动停止时),等待指定时间后,触发事件处理函数。
|--1.等待指定时间后,触发函数。 --思路--> 通过定时器,指定时间time后执行函数func
|--2.触发函数debounce,为document绑定onmousemove事件。
|--3.document.onmouseover = debounce(触发函数,等待时间)
|--4.移动鼠标,查看后台输出:确实2s后触发func,但是两秒后会触发很多个func。why?
|--5.原因:执行了debounce函数,给移动轨迹的起点到终点的“每一点”都绑定了
function,而每一个function都有一个定时器,起点的function里定时器,到了两秒以后就会执行func
函数,然后输出内容。我们的目的是只在终点的function里设置一个定时器,然后终点后两秒,输出
内容。解决办法:鼠标轨迹想想为由1~10个点组成,起点1绑定的function里timeout=1,点2的function里
timeout = 2 ... ...点9的function里timeout=9,终点10的function里timeout=10,我们其实只希望留下最后
一个定时任务,那么就把终点前的所有定时任务timeout清空,clearTimeout(timeout)。只在鼠标停止的
那一点绑定一个定时任务。前提是在time时间返回内。不然任务中处理函数已经被执行。
|--6.查看效果:
三、节流(throttle)
|--案例:这次我们通过scroll事件来演示节流方案
|--解决方案:通过节流函数
|--封装节流函数分析:当触发事件时,每指定时间触发一次事件处理函数。
|--1.当用户持续触发这个函数时,即前后两次触发间隔小于指定时间,函数不会立即触发函数,会在指定
时间后触发函数。
|--2.为什么now-prevTime>time触发函数,因为我们的目的是每隔两秒触发一次scrollFn,如果前后两次
间隔小于两秒,那么正确理解就是不应该执行scrollFn,只有大于2s才会每个两秒进行触发scrollFn。
|--节流函数(定时器实现)
|--思路非常简单:只有当timeout等于null的时候才添加定时任务。每两秒timeout等于null。即每两秒
触发一次func。
四、扩展
|--防抖
|--防抖(非立即执行):上面的例子中防抖函数时非立即执行,即一开始不会执行,等停止动作后,隔指定
时间才执行函数,整个过程执行一次函数。如下图(完整函数)
|--防抖(立即执行):scroll刚开始的时候,就触发一次函数,之后每次scroll结束的时候,隔执行时间触发
一次函数。
|--防抖(终极封装):通过传入参数,来判断是采用立即执行还是非立即执行。
|--节流
|--节流(时间戳):每两秒改变div背景颜色。
|--注意:这里有个小问题需要注意,当我们鼠标刚进入div中,就立马改变的颜色,为什么?如何不让刚进
如div就触发changeColor,这里节流也可以分为立即和非立即执行,其实很简单,突破口就是prevTime。
完善一下时间戳的节流版本:
|--节流(定时器)