唯品秀前端博客

有些浏览器事件会被用户在很短的时间内触发很多次,例如点击事件或滚动页面。如果你给窗口滚动事件添加一个事件监听函数(事件句柄),然后用户不停地快速上下滚动页面,那你的事件可能在一秒之内都会被触发很多次,这会导致严重的性能问题,比如说你的页面卡住了(假死),所以我们需要降低触发回调的频率。

下面就说一下优化这种高频执行js的方法,来提高页面速度和性能。

预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新的时间周期。(设置阈值)

函数防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>
   
    <head>
        <meta charset="utf-8">
        <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
        <title>函数防抖 - 打开控制台,滚动你的鼠标小滑轮试试看</title>
        <style>
</style>
    </head>
   
    <body style="height:2000px;">
            <h1>函数防抖</h1>

    </body>
    <script src="./jquery-2.1.4.min.js"></script>
    <script>
        var isThrottle = true; //初始化无需走节流
        var setTimer = null; //初始化定时器

        var throttle = function(fn, time) {
            clearInterval(setTimer)
            var time = time || 300;
            if (isThrottle) { //注意:在这里第一次滚动时候我们是需要立马执行函数的,真正的防抖是从第二次开始
                fn();
                isThrottle = false;
                return false;
                /*细节:这里如果你不return false阻断代码往下执行,那么在第一次时候实际还会走下面的else,也就是触发了两次,(因为滚轮触发的事件频率很高,第一次节流(else中)的事件会紧接着初始化第一次未节流事件去执行了)*/
            } else {
                console.log('高频触发滚动事件中')
                setTimer = setTimeout(function() {
                    fn();
                    isThrottle = true;
                    console.log('上一次打印是节流执行。。。')
                }, time)
            }
        }

        function conduct() {
            console.log("1")
        }
        $(document).scroll(function() {
            throttle(conduct, 1000);
        })
    </script>

</html>

注意:当你第一次滚动时候,方法不会执行,这当然是属于Bug了,在第一次滚动时候我们应该第一时间执行这个方法,也就是说,真正节流应该是从第二次滚动时候才开始进行,也就是所谓的防抖,它的做法是限制下次函数调用之前必须等待的时间间隔,

如果想处理好真正的节流,很显然,仅仅上面这样处理方式还是不够的,假设用户在mac触摸板下不停的滚动(我也是用mac才发现这个bug)这时候因为每次都会去触发节流函数,但是每次还没执行就被上一个清除定时器给清除了,所以在中途一直不会触发节流,只有每次用户停止才会去触发,很显然不可取,违背了我们的初衷,我们想要的是在第一次立即出发,中间高频率操作过程中间隔一定的时间去更新去出发,而不是必须傻傻的等待用户高频率触发完成后再去触发一次

在线一览

优化封装函数节流方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
    <title>函数节流、防抖 - 打开控制台,滚动你的鼠标小滑轮试试看</title>
    <style>
        body {
            background: #fff;
            text-align: center;
        }

        h1 {
            font-size: 24px;
            line-height: 36px;
            margin-top: 100px;
            font-weight: normal;
            font-family: "微软雅黑"
        }

        a {
            color: #ed145b;
        }
    </style>
</head>

<body style="height:2000px;">
    <h1>函数节流、防抖</h1>
    <p><a href="./index.html">点击前往—>函数防抖(并非节流)</a></p>
</body>
<script src="./jquery-2.1.4.min.js"></script>
<script>
    function conduct(fn, delay, preTime) {
        var timer;
        var initTime = new Date(); // 初始时间点
        console.log('初始化')
        return function (arg) {
            var nowTime = new Date(); // 当前最新时间
            clearTimeout(timer)
            if (nowTime - initTime < preTime) { // 两次操作是否小于预设限制时间(preTime)
                timer = setTimeout(() => {
                    fn(arg);
                    initTime = nowTime;
                }, delay)
            } else {
                fn(arg);
                initTime = nowTime;
            }
        }
    }

    function Fn(data) {
        console.log(data)
    }
    var throttle = conduct(Fn, 1000, 2000)
    $(document).scroll(function () {
        throttle('1');
    })
</script>

</html>

在线一览

最后解释下节流和防抖区别

节流:n秒内只运行一次,若在 n 秒内重复触发,只有一次生效

防抖:n秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

一个经典的比喻:想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应,假设电梯有两种运行策略 debounce 和 throttle,超时设定为15秒,不考虑容量限制,电梯第一个人进来后,15秒后准时运送一次,这是节流。电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖。

本站所有文章、图片、资源等如无特殊说明或标注,均为来自互联网或者站长原创,版权归原作者所有;仅作为个人学习、研究以及欣赏!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理,邮箱:343049466@qq.com
赞(8) 打赏
标签:

上一篇:

下一篇:

相关推荐

0 条评论关于"关于js函数节流与函数防抖【完美解决】"

表情

最新评论

    暂无留言哦~~
谢谢你请我吃鸡腿*^_^*

支付宝扫一扫打赏

微信扫一扫打赏