美文网首页让前端飞JavaScript 进阶营前端开发笔记
javaScript性能优化:防抖和节流由浅入深的小实例

javaScript性能优化:防抖和节流由浅入深的小实例

作者: 果然 | 来源:发表于2019-04-04 11:44 被阅读4次
    防抖和节流由浅入深的小实例

    网上关于防抖和节流的文章五花八门,

    有些人还把防抖和节流的概念搞混了,

    有些人写的代码只提出概念,

    没有实际应用的实例,

    这导致大家看完了,也理解了概念原理,但是实际应用中,把它封装成为函数,并在多事件调用的时候就不会做了。

    我写了一些小小的实例,大家可以把代码粘贴到本地,实际测试一下,

    既能明白防抖和节流两个问题的区别,也能实际应用在事件中。

    html code:

    <body style="padding-top:50px;">
        <nav class="navbar fixed-top navbar-expand-lg navbar-light " id="nav6" >
            <div class="container">
                <a class="navbar-brand" href="#">防抖与节流</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarColor03">
                    <ul class="navbar-nav mr-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">Features</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">Pricing</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">About</a>
                    </li>
                    </ul>
                    <form class="form-inline my-2 my-lg-0">
                    <input class="form-control mr-sm-2" type="text" placeholder="Search">
                    <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
                    </form>
                </div>
            </div>
        </nav>
        <div class="container" style="height:3000px;">
            <div class="row mt-5">
                <div class="col">
                    <div class="alert alert-dismissible alert-primary">
                        <button type="button" class="btn btn-warning" id="btn1">点击增加</button>
                        <strong id="sum1">00</strong> 节流前
                    </div>
                </div>
                <div class="col">
                    <div class="alert alert-dismissible alert-primary">
                        <button type="button" class="btn btn-warning" id="btn2">点击增加</button>
                        <strong id="sum2">00</strong> 使用if节流后
                    </div>
                </div>
                <div class="col">
                        <div class="alert alert-dismissible alert-primary">
                            <button type="button" class="btn btn-warning" id="btn3">点击增加</button>
                            <strong id="sum3">00</strong> 使用setTimeout防抖
                        </div>
                    </div>
            </div>
            <div class="row">
                    <div class="col">
                        <div class="alert alert-dismissible alert-primary">
                            <button type="button" class="btn btn-warning" id="btn4">点击增加</button>
                            <strong id="sum4">00</strong> 节流加防抖
                        </div>
                    </div>
                    <div class="col">
                        <div class="alert alert-dismissible alert-primary">
                            <div class="form-group">
                                <label class="col-form-label " for="input5">在input上使用防抖</label>
                                <input type="text" class="form-control" placeholder="请输入内容" id="input5">
                            </div>
                            <p >在input上使用防抖</p>
                            <ul class="list-group list-group-flush" id="text5">
                            </ul>
                            
                        </div>
                    </div>
                    <div class="col">
                            <div class="alert alert-dismissible alert-primary">
                                <button type="button" class="btn btn-warning" id="btn6">点击增加</button>
                                <strong id="sum6">00</strong> 备用
                            </div>
                        </div>
                </div>
        </div>
    </body>
    

    css:

    <link rel="stylesheet" type="text/css" href="https://bootswatch.com/4/solar/bootstrap.min.css" />
    

    js code:

    节流前

    var sum1 = document.getElementById('sum1');
    var btn1 = document.getElementById('btn1');
    btn1.onclick = function (){
        sum1.innerText = parseInt(sum1.innerText)+ 1;
    }
    

    这个时候,你点击按钮就发现,点的越快,数值增加的越快。

    性能优化:降低代码执行频率

    使用if节流后

    var sum2 = document.getElementById('sum2');
    var btn2 = document.getElementById('btn2');
    function throttle2 (fn,t){
    var lastTime = 0;
    return function(e){
        var nowTime = new Date().getTime();
        if(nowTime - lastTime > t){
    fn.apply(this, arguments);
    lastTime = nowTime;
        }
    }
    }
    function click2 (e){
        //console.log(this, e);
        sum2.innerText = parseInt(sum2.innerText) + 1;
    }
    btn2.onclick = throttle2(click2,1000);
    

    添加节流后,你点击按钮再快,数值还是按照1000一个的速度增加的。

    我已经将节流操作,封装为一个函数,只需调用这个函数,就能给你需要添加的事件,添加上节流功能。

    使用setTimeout防抖

    var sum3 = document.getElementById('sum3');
    var btn3 = document.getElementById('btn3');
    function debounce3(fn,t){
    var timer = null;
    return function(){
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function(){
            fn.apply(context,args);
        }, t);
     }
    }
    function click3 (e){
        console.log(this, e);
        sum3.innerText = parseInt(sum3.innerText) + 1;
    }
    btn3.onclick = debounce3(click3,1000);
    
    

    同样的事件,使用防抖,你会发现,和节流不同的是,你每次快速点击的过程中,是不计算时间的,只有你停止点击按钮,才开始计时,

    这里我定的时间是1000毫秒,你可以方便的在调用事件的时候修改时间。

    我们还可以把防抖和节流一起使用,

    防抖+节流,使用if+setTimeout

    var sum4 = document.getElementById('sum4');
    var btn4 = document.getElementById('btn4');
    function throttle4(fn,n,t){
    var timer = null, begin = new Date();
    return function(){
        var context = this, args = arguments,current = new Date();
        clearTimeout(timer);
        if (current-begin>=n) {
            fn.apply(context,args);
            begin = current;
        } else {
            timer = setTimeout(function(){
                fn.apply(context,args);
            }, t);
        }
        
     }
    }
    function click4 (e){
        console.log(this, e);
        sum4.innerText = parseInt(sum4.innerText) + 1;
    }
    btn4.onclick = throttle4(click4,1000,500);
    

    我把上面的事件都写成一个类型--按钮点击,方便大家比较差异。

    下面是防抖的其他应用。

    在input输入框上使用setTimeout防抖

    var text5 = document.getElementById('text5');
    var input5 = document.getElementById('input5');
    function debounce5(fn,t){
    var timer = null;
    return function(){
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function(){
            fn.apply(context,args);
        }, t);
     }
    }
    function ajax5 (e){
        //console.log(this, e);
        var oLi = document.createElement('li');
        oLi.setAttribute('class', 'list-group-item');
        oLi.innerText = input5.value;
        text5.appendChild(oLi);
        //text5.innerText = input5.value;
    }
    input5.oninput = debounce3(ajax5,1000);
    
    

    这个在百度搜索上很常用,当你输入一些词语的时候,不会每时每刻,每个字都发送到服务器,去请求数据,只有你输入停顿之后,才显示搜索结果。

    以上,都是大白话的说法,下面用比较严谨的说法总结一下:

    总结:防抖的原理:

    通过setTimeout设置毫秒时间,在你触发事件后,n秒内没有再次触发事件,处理函数才会执行,如果在这一段时间来到之前,又一次触发了事件,那就重新计时。

    用户停止输入的时候,才触发查询的请求。

    下面是节流的其他应用

    把函数节流,应用在滚动事件onscroll上

    这个实例,实现了顶部导航条滚动变色的功能。

    var body = document.getElementsByTagName('body')[0];
    var oNav = document.getElementById('nav6');
    function changeColor(){
        //console.log("看看调用了几次?");
        var t = document.documentElement.scrollTop || document.body.scrollTop;
        var classVal;
            if (t > 200) {
               oNav.style.backgroundColor = "#B58900";
            } else {
               oNav.style.backgroundColor = "#FDF6E3";
            }  
    }
    body.onscroll = throttle2(changeColor,1000);
    
    

    使用节流前,你每滚动一下都发出大量的请求,

    使用节流后,你不停地滚动页面结束之后,才发出请求。

    总结:

    节流保证了一段时间内,核心代码只执行一次

    每间隔某个时间去执行某函数,避免函数的过多执行

    相关文章

      网友评论

        本文标题:javaScript性能优化:防抖和节流由浅入深的小实例

        本文链接:https://www.haomeiwen.com/subject/xhjfiqtx.html