原生JS實現(xiàn)懶加載與函數(shù)節(jié)流方法

先寫下標題盗似,今晚寫這個博客~

昨晚改項目BUG改的太晚了拄氯,實在沒空寫该窗,只能放在今天寫咯~

最近寫的小項目正好遇到需要懶加載和函數(shù)節(jié)流,查了資料了解了一下原理“柘現(xiàn)在寫個博客總結一下查找到的資料并簡單用JS實現(xiàn)一下挑豌,以便以后查閱~
注:本文未沒有介紹預加載與函數(shù)防抖,主要是暫時未遇上這兩個需求墩崩,日后有機會再補充氓英!

懶加載

什么是懶加載呢?

  • 懶加載又稱作延遲加載(英語:lazyload)鹦筹,通俗的說一下就是訪問一個網(wǎng)頁的時候铝阐,先把圖片的路徑換成固定的一張圖讓其先占好位置(即占位圖)。當頁面滾動到這張圖片出現(xiàn)在頁面可視區(qū)域內時立即設置圖片的真實路徑铐拐,這便是懶加載饰迹。

為什么要用懶加載呢?

  • 簡單來說是為了優(yōu)化網(wǎng)頁余舶,加快網(wǎng)頁載入速度啊鸭。說具體一點呢就是頁面里的內容實在太多了,比如隨便打開淘寶匿值、京東等網(wǎng)上商城的網(wǎng)頁赠制,頁面往下滾你可以看到有非常多的圖片,這些圖片大小不一,有的幾百k有的可能要1m了钟些。如果當用戶進入頁面時將這些圖片全部都展示出來烟号,那可能耗時太長,用戶等的黃花菜都涼了政恍。汪拥。。
  • 所以可以使用懶加載先展示在瀏覽器可視區(qū)域內的圖片篙耗,加快頁面載入速度~

那接下來我就簡單用JS實現(xiàn)一下懶加載迫筑,代碼如下:

// 先給頁面內所有需要懶加載的圖片賦予'lazyload'的類屬性
// 然后把圖片正確的地址放在'data-src'屬性中,如<img data-src="http://xxx.jpg">
let images = document.querySelectorAll('.lazyload') // 查找所有包含lazyload類屬性的標簽
let imgs = [].slice.call(images) // images是一個偽數(shù)組(對象)宗弯,將images轉為真的數(shù)組
// let imgs = Arrary.from(images) 功能與上面一樣脯燃,為ES6語法
let onscroll = function(){
  if(imgs.length === 0){ return window.removeEventListener('scroll', onscroll)}
  // 判斷imgs這個數(shù)組是否為空,如果為空就代表頁面內沒有需要懶加載的圖片蒙保,刪除監(jiān)聽滾動的事件
  imgs.filter( (img)=> { img.classList.contains('lazyload') })
  // 過濾掉imgs數(shù)組中不包含類名為'lazyload'的標簽
  imgs.forEach((img)=>{
    if(inViewport(img)){
      loadImage(img) // 如果此圖片出現(xiàn)在視口內就設置圖片的真實路徑
    }
  })
}
window.addEventListener('scroll', onscroll) // 監(jiān)聽滾動事件辕棚,當滾動時觸發(fā)onscroll
window.dispatchEvent(new Event('scroll'))
// 這行代碼作用是讓瀏覽器自動執(zhí)行一下滾動事件,因為如果載入頁面時瀏覽器自動沒有執(zhí)行滾動事件邓厕,那么此時在視口內的圖片都沒有真實的圖片地址

function inViewport(img){
  let { top, left, bottom, right } = img.getBoundingClientRect()
  // 調用getBoundingClientRect()這個API逝嚎,讀取當前圖片上下左右各邊距離視口頂部和視口左邊的值,并賦值給相應變量(這里使用的是ES6語法)
  let vpHeight = document.documentElement.clientHeight // 獲取視口高度
  let vpWidth = document.documentElement.clientWidth // 獲取視口寬度
  return (( top > 0 && top < vpHeight || bottom > 0 && bottom < vpHeight ) && 
  (left > 0 && left < vpWidth || right > 0 && right < vpWidth ))
  // 這行代碼返回布爾值详恼,圖片在視口內返回true懈糯,不在視口內返回false
}

function loadImage(img){
  let image = new Image()
  // 創(chuàng)建一個image對象
  image.src = img.dataset.src
  // 讀取img的'data-src'屬性,將圖片真實地址賦給image的src屬性单雾,相當于給瀏覽器緩存了這張真實的圖片
  image.onload = function(){
    img.src = image.src
   // 當瀏覽器加載緩存的圖片時,將圖片真實地址放到此img標簽內她紫,那此img標簽的真實圖片便可直接展示出來
    img.classList.remove('lazyload') // 刪除img標簽的'lazyload'類屬性
  }
}

函數(shù)節(jié)流

什么是函數(shù)節(jié)流呢硅堆?

  • 這里先說一下什么是節(jié)流:比如你家的水龍頭開到最大檔,那水龍頭里的水會嘩嘩的流下來贿讹,但是如果你把水龍頭擰緊直到水以水滴的形式流出渐逃,那你就會發(fā)現(xiàn)每隔一段時間才會有一滴水流出
  • 函數(shù)節(jié)流(英語:throttle)也就是設定一個執(zhí)行的周期,前一次調用動作到當前調用動作的時間間隔大于或等于設定的執(zhí)行周期時就執(zhí)行該動作(如果時間間隔小于設定的執(zhí)行周期時民褂,就等時間到達設定的執(zhí)行周期再執(zhí)行動作)茄菊,然后進入下一個周期。

為什么要用函數(shù)節(jié)流呢赊堪?

  • 主要是為了限制函數(shù)的執(zhí)行頻率面殖,用于優(yōu)化函數(shù)觸發(fā)頻率過高而導致響應速度跟不上觸發(fā)頻率,出現(xiàn)bug哭廉、延遲脊僚、卡頓等現(xiàn)象。

那接下來我就簡單用JS實現(xiàn)一下函數(shù)節(jié)流遵绰,代碼如下:

function throttle(func, wait){
// 設置一個名為throttle的函數(shù)辽幌,此函數(shù)可接受兩個參數(shù)增淹,一個參數(shù)為執(zhí)行函數(shù),另一個參數(shù)為執(zhí)行周期
  let prev, timer
  // 聲明兩個變量乌企,一個為前一次調用動作的時間虑润,一個為計時器
  return function fn(){
  // 返回名為'fn'的函數(shù)
    let curr = Date.now()
    // 獲取當前時間
    let diff = curr - prev
    // 獲取前一次調用動作到當前調用動作的時間間隔
    if(!prev || diff >= wait){
      func()
      // 如果調是第一次用動作或時間間隔大于等于執(zhí)行周期,則執(zhí)行所傳入的函數(shù)
      prev = curr // 將當前時間賦值給前一次調用動作的時間
    }else if(diff < wait){
      clearTimeout(timer) // 如果時間間隔小于執(zhí)行周期(即在時間間隔內又觸發(fā)了一次事件)加酵,就清空原先的定時器
      timer = setTimeout(fn, wait - diff) // 設置一個新的定時器拳喻,等時間到達設定的執(zhí)行周期再執(zhí)行函數(shù)'fn'
    }
  }
}

結語:以上就是我根據(jù)查找的資料總結實現(xiàn)的懶加載與函數(shù)節(jié)流。如果其中有問題虽画,麻煩在評論中指出舞蔽。謝謝~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市码撰,隨后出現(xiàn)的幾起案子渗柿,更是在濱河造成了極大的恐慌,老刑警劉巖脖岛,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朵栖,死亡現(xiàn)場離奇詭異,居然都是意外死亡柴梆,警方通過查閱死者的電腦和手機陨溅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绍在,“玉大人门扇,你說我怎么就攤上這事〕ザ桑” “怎么了臼寄?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長溜宽。 經(jīng)常有香客問我吉拳,道長,這世上最難降的妖魔是什么适揉? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任留攒,我火速辦了婚禮,結果婚禮上嫉嘀,老公的妹妹穿的比我還像新娘炼邀。我一直安慰自己,他們只是感情好剪侮,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布汤善。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪红淡。 梳的紋絲不亂的頭發(fā)上不狮,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天,我揣著相機與錄音在旱,去河邊找鬼摇零。 笑死,一個胖子當著我的面吹牛桶蝎,可吹牛的內容都是我干的驻仅。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼登渣,長吁一口氣:“原來是場噩夢啊……” “哼噪服!你這毒婦竟也來了?” 一聲冷哼從身側響起胜茧,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤粘优,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后呻顽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雹顺,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年廊遍,在試婚紗的時候發(fā)現(xiàn)自己被綠了嬉愧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡喉前,死狀恐怖没酣,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情卵迂,我是刑警寧澤裕便,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站狭握,受9級特大地震影響,放射性物質發(fā)生泄漏疯溺。R本人自食惡果不足惜论颅,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囱嫩。 院中可真熱鬧恃疯,春花似錦、人聲如沸墨闲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盾鳞,卻和暖如春犬性,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腾仅。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工乒裆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人推励。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓鹤耍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親验辞。 傳聞我的和親對象是個殘疾皇子稿黄,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內容