關(guān)于js函數(shù)節(jié)流和去抖動

實際上啊,今天早上本來想干點別的,但是在吃早餐的時候瀏覽了下掘金,然后看到了這篇博文<a >Jake的關(guān)于圖片懶加載</a> 就順帶研究了一波函數(shù)節(jié)流和去抖動問題。

為什么要函數(shù)節(jié)流

以下場景往往由于事件頻繁被觸發(fā),因而頻繁執(zhí)行DOM操作、資源加載等重行為,導(dǎo)致UI停頓甚至瀏覽器崩潰。

  1. window對象的resize、scroll事件
  2. 拖拽時的mousemove事件
  3. 射擊游戲中的mousedown、keydown事件
  4. 文字輸入、自動完成的keyup事件
    例子以scroll事件進行解析
    <code>
    window.onscroll = function(){
    lazyload();
    //throttle(lazyload,window);
    };
    function lazyload(){
    console.log("scroll執(zhí)行了"+scrollnum);
    }
    </code>


    滾動一次

    我們的本意只是讓鼠標(biāo)滾動一次執(zhí)行一次滾動函數(shù),但是window的onscroll函數(shù)并不是等scroll結(jié)束之后才會調(diào)用,鼠標(biāo)滾動或拖動滾動條,就會不停的觸發(fā)scroll事件,如果處理的東西多,低版本的IE也會陷入假死狀態(tài)。


解決辦法

debounce

抖動:如果用手指一直按住一個彈簧,它將不會彈起直到你松手為止。 也就是說當(dāng)調(diào)用動作n毫秒后,才會執(zhí)行該動作,若在這n毫秒內(nèi)又調(diào)用此動作則將重新計算執(zhí)行時間。這種比較適合window的resize事件,實際需求大多為停止改變大小n毫秒后執(zhí)行后續(xù)處理;而其他事件大多的需求是以一定的頻率執(zhí)行后續(xù)處理。針對這兩種需求就出現(xiàn)了和throttle兩種解決辦法。

  1. 去抖1
    <code>
    window.onscroll = function(){
    //lazyload();
    debounce(lazyload,window);
    };
    function debounce(method,context){
    clearTimeout(method.timeout);
    method.timeout = setTimeout(function(){
    method.call(context);
    },500);
    }
    function lazyload(){
    console.log("scroll執(zhí)行了"+scrollnum);
    }
    </code>
    效果如下,可以看出只執(zhí)行了一次lazyload函數(shù):


    節(jié)流之后的滾動一次的執(zhí)行效果

    利用定時器,讓函數(shù)執(zhí)行延遲500毫秒,在500毫秒內(nèi)如果有函數(shù)又被調(diào)用則刪除上一次調(diào)用,這次調(diào)用500毫秒后執(zhí)行,如此往復(fù)
    2.去抖2.
    還有一種節(jié)流方式,是通過返回閉包的形式,可以設(shè)置延遲時間,兩者運行的結(jié)果是一樣,但是我在實際操作的時候設(shè)置延遲500時,滾動過了一會才執(zhí)行了,設(shè)置為delay為100的時候在視覺上就沒有感覺延遲。而且函數(shù)也只滾動了一次。
    <code>
    function debounce1(method,delay){
    var timer = null;
    return function(){
    var context = this,args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function(){
    method.apply(context,args);
    },delay);
    }
    }
    </code>

throttle

當(dāng)我一直滾動鼠標(biāo)的時候,lazyload函數(shù)就會不斷被延遲,這樣只有停下來的時候才會執(zhí)行,那么再有些需要及時顯示的情況下,就顯得不那么友好了(對于實現(xiàn)keyup事件的提示也沒有意義了),所以可以為函數(shù)添加一個參數(shù)作為到固定間隔必須執(zhí)行,到了這個時間間隔就必須執(zhí)行,這個時候就引入了節(jié)流:
節(jié)流:如果將水龍頭擰緊直到水是以水滴的形式流出,那你會發(fā)現(xiàn)每隔一段時間,就會有一滴水流出。也就是會說預(yù)先設(shè)定一個執(zhí)行周期,當(dāng)調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進入下一個新周期
代碼如下:
<code>
function throttle2(method, delay, time) {
var timeout,startTime = new Date();
return function() {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
// 如果達到了規(guī)定的觸發(fā)時間間隔,觸發(fā) handler
if (curTime - startTime >= time) {
method.apply(context, args);
startTime = curTime;
// 沒達到觸發(fā)間隔,重新設(shè)定定時器
} else {
timeout = setTimeout(method, delay);
}
};
</code>



在這個函數(shù)中,當(dāng)一次時間較長的時候還是會執(zhí)行兩次,而不是等滾動停止之后再執(zhí)行。達到了想要的效果,既沒有頻繁的執(zhí)行也沒有最后執(zhí)行

引一波圖片懶加載。

頁面加載速度影響最大的就是圖片,一張普通的圖片可以達到幾M的大小,而代碼也許就只有幾十KB。當(dāng)頁面圖片很多時,頁面的加載速度緩慢,幾S鐘內(nèi)頁面沒有加載完成,也許會失去很多的用戶。
所以,對于圖片過多的頁面,為了加速頁面加載速度,所以很多時候我們需要將頁面內(nèi)未出現(xiàn)在可視區(qū)域內(nèi)的圖片先不做加載, 等到滾動到可視區(qū)域后再去加載。這樣子對于頁面加載性能上會有很大的提升,也提高了用戶體驗。

將頁面中的img標(biāo)簽src指向一張小圖片或者src為空,然后定義data-src(這個屬性可以自定義命名,我才用data-src)屬性指向真實的圖片。src指向一張默認(rèn)的圖片,否則當(dāng)src為空時也會向服務(wù)器發(fā)送一次請求??梢灾赶騦oading的地址

只有當(dāng)滾動到該圖片的時候才將該圖片的src換為data-src。這樣就能加速加載速度。


這樣一開始頁面只需要加載一張圖片
滾動兩次之后

參考網(wǎng)址:https://gold.xitu.io/post/583b10640ce463006ba2a71a
http://www.cnblogs.com/dolphinX/p/3403821.html
http://blog.csdn.net/fengyinchao/article/details/50749317
https://segmentfault.com/a/1190000002764479
http://www.jb51.net/article/49502.htm
http://www.cnblogs.com/fsjohnhuang/p/4147810.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 8,118評論 2 17
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 7,324評論 0 17
  • HTML5面試題總結(jié)1.基礎(chǔ)問題 = 和 == 和 === 的區(qū)別?= : 用于賦值 == : 用于判斷 === ...
    LorenaLu閱讀 1,398評論 0 4
  • 人生就像是煙花,變化莫測,你永遠猜不準(zhǔn),下一刻會是什么顏色,什么形狀,會發(fā)生什么,你只知道,你的人生并不像煙...
    小名博涵閱讀 270評論 0 0
  • 最近真是怠惰的季節(jié),書也不想看,電視劇也不想看(雖然還是看了不少),課題也沒能理想(雖然沒日沒夜仿真)。 看這本書...
    Tunatime閱讀 291評論 0 0

友情鏈接更多精彩內(nèi)容