最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 防抖与节流

    正文概述 掘金(Deno)   2021-01-05   435

    定义

    防抖与节流

    在JavaScript中,函数的防抖和节流不是什么新鲜话题,与之对应的文章也数不胜数,但是看再多都不如自己亲自做一遍,写一遍来的通透一些。本人在这之前对防抖和节流一直处于一个比较朦胧的印象,正好这次用到了,写下此文予以记录两者区别。

    • 防抖效果

      1秒内。只要有新的触发产生:从0开始计时。

    • 节流效果

      1秒内。只要有新的触发产生:无效,除非之前的操作执行完。

    场景

    说了这些,先来看看如何使用?假设我们有一个这样的场景需求:

    我们需要监控页面的鼠标移动事件,会频繁的触发 mousemove ,而 mousemove 里面有着一些复杂的计算,我们假定事件里面需要进行 10 万次循环插入数组操作来模拟复杂计算。那么就会导致一个严重的性能问题。反反复复的进行计算,而实际上 mousemove 实在是太勤劳了,我们当中不需要那么“及时”的触发,否则可能会导致占用其他操作时间,例如我们的页面卡顿。于是我们需要引入防抖和节流。

    先来看下我们即将进行的模拟复杂操作:

    let arr = [];
    for (let i = 0; i <= 100000; i++) {
      arr.push(Math.random())
    }
    arr.sort((x, y) => y - x)
    console.log(arr.join())
    

    (多余的解读:随机生成10万的数字,从大到小排列,最后拼接输出)

    可以看到计算是比较费时的,接下来我们先上代码,mousemove 下的展示:

     function handle({
            clientY,
            clientX
        }) {
            let arr = [];
            for (let i = 0; i <= 100000; i++) {
                arr.push(Math.random())
            }
            arr.sort((x, y) => y - x)
            console.log(arr.join())
    		document.body.innerText = `x:${clientY},y:${clientX}`
        }
        document.addEventListener('mousemove', handle)
    

    解读:handle函数用于处理 mousemove 的操作,将鼠标的坐标显示到页面上。

    可以发现现在页面已经有些卡顿了,我们接下来就借助防抖和节流来优化目前的页面体验。

    防抖

    代码:

    function debounce(fn, time) {
            let timer;//记录定时器
            return function(event) {//返回一个新的函数
                clearTimeout(timer)//如果又被触发了,清除上次的定时器
                document.body.innerText = '鼠标停下展示结果'
                timer = setTimeout(() => {//在下一次事件循环触发,并且记录定时器id,以用于需要清理的时候。
                    fn(event)
                }, time)
            }
        }
    document.addEventListener('mousemove', debounce(handle, 100))//传入handle函数,100毫秒后触发
    

    页面上展示后可以发现:鼠标一直滑动的时候,页面没动静,但是一旦鼠标停下 100 毫秒以后开始显示内容。

    节流

    代码:

     function throttle(fn, time) {
            let flag = false;//设置标志位
            return function(event) {
                if (flag) return false;//如果标志位有定时器id,则说明之前有过任务,撤销本次任务。
                flag = setTimeout(() => {//记录任务id
                    fn(event)
                    flag = false;//任务执行完毕,标志位还原
                }, time)
            }
        }
    document.addEventListener('mousemove', throttle(handle, 100))//传入handle函数,100毫秒后触发
    

    页面上展示后可以发现:鼠标滑动的时候,页面也一直在计算,不过不管如何滑动,都会按照指定的时间频率来进行,不会大量触发。

    当然实现防抖和节流未必只有我展示的方式,代码是灵活的,例如第二种throttle方式:

    function throttle2(fn, time) {
            let begin = new Date();//记录时间
            return function(event) {
                if (new Date() - begin < time) return false;//减去时间看看差了多少,不满足时间直接return
                fn(event)
                begin = new Date()//重置本次记录时间,以便于下次进行比对
            }
        }
    

    回到开头的图

    防抖与节流

    防抖和节流组合形式:

    function throttle(fn, time, fn2, time2) {
            let flag = false;//节流标志
            let timer;//防抖定时器标志
            return function(event) {
                clearTimeout(timer)//清理防抖定时器
                if (flag) return false;
                flag = setTimeout(() => {
                    fn(event)//页面显示内容需要实时性比较强,不需要大量计算的ui更新放在这里进行
                    flag = false;
                    timer = setTimeout(() => {//延时执行复杂运算,鼠标不动的时候就可以有时间进行复杂运算更新。
                        fn2()
                    }, time2)
                }, time)
            }
        }
        
         function handle({
            clientY,
            clientX
        }) {
            document.body.innerText = `x:${clientY},y:${clientX}`
        }
    
        function handle2() {
            let arr = [];
            for (let i = 0; i <= 100000; i++) {
                arr.push(Math.random())
            }
            arr.sort((x, y) => y - x)
            console.log(arr.join())
    
        }
        document.addEventListener('mousemove', throttle(handle, 10, handle2,50))
    
    • 以上代码便可很好的解决页面卡顿,鼠标移动同时,需要移动到某个地方进行一个大量计算。

    总结

    • 这里可以简单总结一下这个场景下防抖和节流的使用:
      • 防抖:适合复杂运算的时候不要让它们过于频繁的执行,等页面“冷静”下来再去执行。
      • 节流:必须要间隔固定时间执行一次,ui界面等高优先级的事情让它去做。

    多思考,多写写。两者还是很容易区别的~


    起源地下载网 » 防抖与节流

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元