JavaScript函數節流

來源:互聯網
上載者:User

標籤:show   timer   效能   app   html   defer   java   return   sed   

函數節流

  技術一般水平有限,有什麼錯的地方,望大家指正。

  函數節流就是節約函數的調用,讓函數少執行幾次,一般用在onmousemove,onresize這種我們只要稍微一動就會砰砰砰執行多次的事件處理函數上。如果處理函數很複雜有執行很多次就很耗效能關鍵了有的是沒有必要執行的。

  我們先說一個經常遇見的情況,滑鼠放在按鈕上顯示下拉式功能表,滑鼠離開下拉式功能表消失,通常我們這麼寫:

//title表示標題元素,content表示下拉式功能表$("#title").hover(function(){  $("#content").show();},function(){  $("#content").hide();})

  當我們快速划過的時候,會看到下拉式功能表會先出現然後立即隱藏傳說中的閃一下,我們知道使用者快速划過時一般情況下並不是要查看下拉式功能表的,所以我們要避免下拉式功能表閃一下的這種事,通常我們的做法就是加一個定時器:

var timer;$("#title").hover(function(){    timer = setTimeout(function(){        $("#content").show();    },100)},function(){    clearTimeout(timer);    $("#content").hide();})

  這樣當我們想查看菜單時只要把滑鼠放在標題元素上下拉式功能表就出現了,當我們滑鼠快速划過標題元素時並不會出現下拉式功能表元素,避免了菜單閃一下的尷尬事。

  繼續介紹函數節流。函數節流也是這個套路,假如我們想對onresize事件進行處理(假設handler是一個很複雜的處理函數):

$(window).resize(handler);var a = 1;function handler(){    console.log(a++);}

  我們在改變視窗大小的時候只要稍微動一下處理函數就會執行十幾次,這其實是完全沒必要的,如果處理函數有很多的DOM操作,這是很耗效能的,所以我們要儘可能的減少事件處理函數的執行次數。

  我們也像上一個例子一樣使用一個定時器來實現:

$(window).resize(handler);var a = 1;var timer;function handler(){    timer&&clearTimeout(timer);    timer = setTimeout(function(){        console.log(a++);    },50)}

  在我們改變瀏覽器大小的過程中事件處理函數並沒有執行,只有當停止時才會執行我們的處理函數。為了使用方便可以封裝成一個函數:

$(function(){    $(window).resize(function(e){        defer(this,200,handler)(e);    })})function handler(e){    console.log(e);}/****fn表示事件處理函數**_this表示事件處理函數中的this指向**delay表示延遲時間*/function defer(_this,delay,fn){    return function(){        fn.timer&&clearTimeout(fn.timer);        var arg = arguments;        fn.timer = setTimeout(function(){            fn.apply(_this,arg);        },delay)    }} 

  這種方式在處理onresize事件上還算是實用的但是在onmousemove上就會感覺很尷尬了,對於onmousemove我們通常處理都是標識出一個物體的軌跡,如果用上面的方式那麼在移動的過程中總是清除定時器導致處理函數不執行,當滑鼠停止時處理函數才開始執行,就看到物體直接從起點跳到終點,過程無跡可尋!

  查看這種情況下的拖動效果。

  為了記錄物體運動的軌跡我們需要在一定的間隔內就執行一次onmousemove的事件處理函數:

$(function(){    $("#demo").bind("mousedown",function(e){        var _this = this;        var left = $(this).offset().left;        var top = $(this).offset().top;        var downX = e.pageX;        var downY = e.pageY;        var disX = downX-left;        var disY = downY-top;        $(document).bind("mousemove",function(e){            defer(_this,200,handler)(e,disX,disY);                    })        $(this).bind("mouseup",function(e){            handler.timer&&clearInterval(handler.timer);            $(document).unbind("mousemove");            $(this).unbind("mouseup");        })    })})function handler(e,disX,disY){    var currentX = e.pageX;    var currentY = e.pageY;    $(this).css({"top":currentY-disY+"px","left":currentX-disX+"px"});    console.log(1)}/****fn表示事件處理函數**_this表示事件處理函數中的this指向**delay表示延遲時間**interval表示函數執行的間隔預設50ms*/function defer(_this,delay,fn,interval){    return function(){        fn.timer&&clearTimeout(fn.timer);        var arg = arguments;        var _interval = interval || 50;        fn.start?"":fn.start=+new Date();        var current = +new Date();        if(current-fn.start>=_interval){            fn.start = current;            fn.apply(_this,arg);        }else{            fn.timer = setTimeout(function(){                fn.apply(_this,arg);            },delay)        }        }}

  查看效果。基本使用就是這些更多知識可以在網上查詢。

JavaScript函數節流

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.