Javascript圖片懶加載

原理

一開始將img標簽的src設(shè)置為一張默認圖片局冰,將真實的圖片地址放在data-src上测蘑,監(jiān)聽滾動事件,當圖片進入可視區(qū)域時康二,寫入src真實的圖片地址帮寻。

如何判斷圖片進入了可視區(qū)域?

image.png

對于這樣一個頁面赠摇,圖片即將進入頁面的條件是:圖片距離整個網(wǎng)頁頂部的距離 < 瀏覽器可視區(qū)域的高度 + 滾動條滾動的距離固逗。那么問題就可以分解成三個小點:

①圖片距離整個網(wǎng)頁頂部的距離;

可以通過下面這個方法獲取某個元素到網(wǎng)頁頂部的距離:

function getElementTop (element) {
  let actualTop = element.offsetTop;
  let parent = element.offsetParent;

  while (parent !== null) {
    actualTop += parent.offsetTop;
    parent = parent.offsetParent;
  }

  return actualTop;
}

代碼分析:
offsetTop表示的是元素距離父元素左上角頂點的高度藕帜,offsetParent則表示元素的父元素烫罩。通過不斷遍歷累加高度,就可以得到元素距離網(wǎng)頁頂部的距離洽故。

②瀏覽器可視區(qū)域的高度贝攒;

window.innerHeight

③滾動條滾動的距離。

document.documentElement.scrollTop

懶加載如何實現(xiàn)时甚?

html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="./lazyLoad.css">
</head>
<body>
    <div class="wrapper">
        <img src="./default.jpg" data-src="./dog0.jpg">
        <img src="./default.jpg" data-src="./dog1.jpg">
        <img src="./default.jpg" data-src="./dog2.jpg">
        <img src="./default.jpg" data-src="./dog3.jpg">
        <img src="./default.jpg" data-src="./dog4.jpg">
        <img src="./default.jpg" data-src="./dog5.jpg">
        <img src="./default.jpg" data-src="./dog6.jpg">
    </div>
    <script src="./lazyLoad.js"></script>
</body>
</html>

這里只需要注意到開始時img標簽的src屬性放的是默認的圖片隘弊,真正的圖片地址放在了data-src中

css代碼如下:

.wrapper {
    text-align: center;
}

img {
    display: block;
    margin: 10px auto;
}

js代碼如下:

function lazyLoad () {
  let images = document.querySelectorAll('img');
  for(let i = 0; i < images.length; i++) {
    let image = images[i];
    if (getElementTop(image) <= window.innerHeight + document.documentElement.scrollTop) {
      image.src = image.getAttribute('data-src');
    }
  }
}

function getElementTop (element) {
  let actualTop = element.offsetTop;
  let parent = element.offsetParent;

  while (parent !== null) {
    actualTop += parent.offsetTop;
    parent = parent.offsetParent;
  }

  return actualTop;
}

lazyLoad();

window.onscroll =lazyLoad荒适;

代碼分析:
window.onscroll = lazyload表示在滾動條滾動時觸發(fā)調(diào)用lazyLoad方法梨熙;

在lazyLoad方法中,先通過document.querySelectorAll('img');找到所有的Image(這里只是為了簡化示例刀诬,實際場景中可以通過在需要懶加載的圖片上添加統(tǒng)一的類名咽扇,然后通過querySelectorAll('.類名')來獲取需要懶加載的圖片),依次判斷是否進入了可視區(qū)域內(nèi)。如果進入了可視區(qū)域則做img標簽的src的替換。

需要手動調(diào)用一次lazyLoad方法质欲,在頁面剛load的時候?qū)⒁呀?jīng)在視窗內(nèi)的圖片加載出來树埠。

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

所謂的函數(shù)節(jié)流就是當事件觸發(fā)的頻率很高時,并不是每次都需要去調(diào)用相對應(yīng)的處理函數(shù)嘶伟,以此來提高性能怎憋。比如這里的滾動事件,假設(shè)我們希望至少間隔200ms才釣魚那個一次處理函數(shù)九昧,那么可以新增一個方法

function throttle (delay, action) {
  let last = 0;
  return function () {
    let now = new Date();
    if (now - last > delay) {
      action();
      last = now;
    }
  }
}

然后將window.onscroll =lazyLoad盛霎;改成window.onscroll = throttle(200, lazyLoad)。這個函數(shù)在事件觸發(fā)時耽装,先去判斷本次觸發(fā)的時間和上次觸發(fā)的時間的間隔,如果大于delay期揪, 則運行處理函數(shù)掉奄。

函數(shù)用到了閉包的原理來保存last這個變量,對于閉包簡單的解釋一下就是throttle這個函數(shù)在調(diào)用結(jié)束后凤薛,本來應(yīng)該銷毀掉其內(nèi)部的last變量姓建,但是由于返回的是一個函數(shù),返回的函數(shù)內(nèi)引用了last這個變量缤苫,因此last被一直保存在了內(nèi)存中速兔。

throttle這個方法還有很多可以優(yōu)化的地方,不在這里展開了活玲。主題是懶加載嘛涣狗,后面有空了專門寫一篇函數(shù)節(jié)流方法的文章。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舒憾,一起剝皮案震驚了整個濱河市镀钓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌镀迂,老刑警劉巖丁溅,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異探遵,居然都是意外死亡窟赏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門箱季,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涯穷,“玉大人,你說我怎么就攤上這事藏雏∏笤ィ” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝠嘉。 經(jīng)常有香客問我最疆,道長,這世上最難降的妖魔是什么蚤告? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任努酸,我火速辦了婚禮,結(jié)果婚禮上杜恰,老公的妹妹穿的比我還像新娘获诈。我一直安慰自己,他們只是感情好心褐,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布舔涎。 她就那樣靜靜地躺著,像睡著了一般逗爹。 火紅的嫁衣襯著肌膚如雪亡嫌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天掘而,我揣著相機與錄音挟冠,去河邊找鬼。 笑死袍睡,一個胖子當著我的面吹牛知染,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斑胜,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼控淡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了止潘?” 一聲冷哼從身側(cè)響起逸寓,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎覆山,沒想到半個月后竹伸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡簇宽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年勋篓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魏割。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡譬嚣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钞它,到底是詐尸還是另有隱情拜银,我是刑警寧澤殊鞭,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站尼桶,受9級特大地震影響操灿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泵督,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一趾盐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧小腊,春花似錦救鲤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至入问,卻和暖如春丹锹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背队他。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留峻村,地道東北人麸折。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像粘昨,于是被迫代替她去往敵國和親垢啼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容