二維碼
        企資網(wǎng)

        掃一掃關(guān)注

        當(dāng)前位置: 首頁(yè) » 企資頭條 » 頭條 » 正文

        web前端性能優(yōu)化_圖片加載的優(yōu)化

        放大字體  縮小字體 發(fā)布日期:2021-09-05 02:29:29    作者:企資小編    瀏覽次數(shù):30
        導(dǎo)讀

        作者:麥樂(lè)來(lái)源:恒生LIGHT云社區(qū)圖像延遲加載想要得到更好的性能體驗(yàn),只靠資源壓縮與恰當(dāng)?shù)奈募袷竭x型,是很難滿足期望的。我們還需要針對(duì)資源加載過(guò)程進(jìn)行優(yōu)化。什么是延遲加載?下圖是京東商城的手機(jī)端首頁(yè),

        作者:麥樂(lè)

        來(lái)源:恒生LIGHT云社區(qū)

        圖像延遲加載

        想要得到更好的性能體驗(yàn),只靠資源壓縮與恰當(dāng)?shù)奈募袷竭x型,是很難滿足期望的。我們還需要針對(duì)資源加載過(guò)程進(jìn)行優(yōu)化。

        什么是延遲加載?

        下圖是京東商城的手機(jī)端首頁(yè),當(dāng)元素沒(méi)有滑動(dòng)到視線內(nèi)時(shí),圖片src屬性放置了一個(gè)很小的圖片,init_src屬性放置了真正的圖片,只要當(dāng)該元素滑動(dòng)到視線內(nèi)部,才會(huì)將init_src屬性賦值給src去加載真實(shí)的圖片,這就是一個(gè)簡(jiǎn)單的圖片延遲加載的過(guò)程。

        傳統(tǒng)方式延遲加載

        就是事件監(jiān)聽(tīng)的方式,通過(guò)監(jiān)聽(tīng)scroll事件與resize事件,并在事件的回調(diào)函數(shù)中去判斷,需要進(jìn)行延遲加載的圖片是否進(jìn)入視窗區(qū)域。

        我們只需要關(guān)注三個(gè)屬性。

      1. class屬性,稍后會(huì)在Javascript中使用類(lèi)選擇器選取需要延遲加載處理的〈img〉標(biāo)簽。
      2. src屬性,加載前的占位符圖片,可用base64圖片或低分辨率的圖片。
      3. data-src屬性,通過(guò)該自定義屬性保存圖片真實(shí)的URL外鏈。

        加入頁(yè)面中有多張這樣的圖片需要加載。具體的Javascript實(shí)現(xiàn)邏輯如下,在文檔的DOMContentLoaded事件中,添加延遲加載處理邏輯,首先獲取class屬性名為lazy的所有〈img〉標(biāo)簽,將這些標(biāo)簽暫存在一個(gè)名為lazyImages的數(shù)組中,表示需要進(jìn)行延遲加載但還未加載的圖片集合。當(dāng)一個(gè)圖片被加載后,便將其從lazyImages數(shù)組中移除,直到lazyImages數(shù)組為空時(shí),表示所有待延遲加載的圖片均已經(jīng)加載完成,此時(shí)便可將頁(yè)面滾動(dòng)事件移除。

        這里使用了getBoundingClientRect()函數(shù)獲取元素的相對(duì)位置.

                rectObject = object.getBoundingClientRect();

        rectObject.top:元素上邊到視窗上邊的距離;

        rectObject.right:元素右邊到視窗左邊的距離;

        rectObject.bottom:元素下邊到視窗上邊的距離;

        rectObject.left:元素左邊到視窗左邊的距離;

        對(duì)于只可上下滾動(dòng)的頁(yè)面,判斷一個(gè)圖片元素是否出現(xiàn)在屏幕視窗中的方法其實(shí)顯而易見(jiàn),即當(dāng)元素上邊緣距屏幕視窗頂部的top值小于整個(gè)視窗的高度window.innerHeight時(shí),預(yù)加載的事件處理代碼如下:

        document.addEventListener(DOMContentLoaded, function() {      const imags = [].slice.call(document.querySelector('.lazy'))      const active = false; // 限制函數(shù)被頻繁調(diào)動(dòng)      function load() {        if(active === false) {          active = true          setTimeout(() => {            imags.forEach((img) => {              const objPos = img.getBoundingClientRect();              if(objPos.top <= window.innerHeight && objPos.bottom >=0 && img.display !== 'done') {                img.src = img.dataset.src;                img.classList.remove('lazy')                imags.filter((i) => (i !== img))                if(imags.length === 0) {                  document.removeEventListener('scroll', load)                  window.removeEventListener('resize', load)                  window.removeEventListener('orientationchange', load)                }                }            })            active = false          }, 200)        }      }      document.addEventListener('scroll', load)      window.addEventListener('resize', load)      window.addEventListener('orientationchange', load)    })

        這種方式的有點(diǎn)就是兼容性比較好,缺點(diǎn)是頻繁地進(jìn)行計(jì)算必然會(huì)影響性能,代碼也會(huì)比較繁瑣。

        實(shí)現(xiàn)圖片的延遲加載:Intersection Observer方式

        現(xiàn)代瀏覽器已大多支持了Intersection Observer API,用一句話簡(jiǎn)述:每當(dāng)因頁(yè)面滾動(dòng)或窗口尺寸發(fā)生變化,使得目標(biāo)元素(target)與設(shè)備視窗或其他指定元素產(chǎn)生交集時(shí),便會(huì)觸發(fā)通過(guò)Intersection Observer API配置的回調(diào)函數(shù),在該回調(diào)函數(shù)中進(jìn)行延遲加載的邏輯處理,會(huì)比傳統(tǒng)方式顯得更加簡(jiǎn)潔而高效。

        簡(jiǎn)單來(lái)說(shuō),目標(biāo)元素的可見(jiàn)性變化時(shí),就會(huì)調(diào)用觀察器的回調(diào)函數(shù) callback

        callback一般會(huì)觸發(fā)兩次。一次是目標(biāo)元素剛剛進(jìn)入視口(開(kāi)始可見(jiàn)),另一次是完全離開(kāi)視口(開(kāi)始不可見(jiàn))。

         document.addEventListener(DOMContentLoaded, function() {        const imags = [].slice.call(document.querySelector('.lazy'))        if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {          var lazyImgObserver = new IntersectionObserver((entries, observer) => {            entries.forEach((entry)=> {              if(entry.isIntersecting) {                var lazyImg = entry.target;                lazyImg.src = lazyImg.dataset.src;                lazyImg.classList.remove('lazy');                lazyImgObserver.unobserve(lazyImg)              }            })          })          imags.forEach((img) => {            lazyImgObserver.observe(img)          })        }         })

        這種方式判斷元素是否出現(xiàn)在視窗中更為簡(jiǎn)單直觀,應(yīng)在實(shí)際開(kāi)發(fā)中盡量使用,但其問(wèn)題是并非所有瀏覽器都能兼容。

        (1)做好盡量完備瀏覽器兼容性檢查,對(duì)于兼容Intersection Observer API的瀏覽器,采用這種方式進(jìn)行處理,而對(duì)于不兼容的瀏覽器,則切換回傳統(tǒng)的實(shí)現(xiàn)方式進(jìn)行處理。 (2)使用相應(yīng)兼容的polyfill插件,在W3C官方GitHub賬號(hào)下就有提供。

        實(shí)現(xiàn)圖片的延遲加載:CSS類(lèi)名方式

        這種實(shí)現(xiàn)方式通過(guò)CSS的background-image屬性來(lái)加載圖片,與判斷〈img〉標(biāo)簽src屬性是否有要請(qǐng)求圖片的URL不同,CSS中圖片加載的行為建立在瀏覽器對(duì)文檔分析基礎(chǔ)之上。

          document.addEventListener(DOMContentLoaded, function() {        const imags = [].slice.call(document.querySelector('.lazy'))        if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {          var lazyImgObserver = new IntersectionObserver((entries, observer) => {            entries.forEach((entry)=> {              if(entry.isIntersecting) {                var lazyImg = entry.target;                lazyImg.classList.add('visible');                lazyImgObserver.unobserve(lazyImg)              }            })          })          imags.forEach((img) => {            lazyImgObserver.observe(img)          })        }         })

        這種方式限制于需要提前寫(xiě)好css樣式。

        原生的延遲加載支持

        除了上述通過(guò)開(kāi)發(fā)者手動(dòng)實(shí)現(xiàn)延遲加載邏輯的方式,從Chrome 75版本開(kāi)始,已經(jīng)可以通過(guò)〈img〉和〈iframe〉標(biāo)簽的loading屬性原生支持延遲加載了,loading屬性包含以下三種取值。

        ● lazy:進(jìn)行延遲加載。 ● eager:立即加載。 ● auto:瀏覽器自行決定是否進(jìn)行延遲加載。

        測(cè)試:image標(biāo)簽就是 img

        <!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>document</title>  <!-- <script src=nnzzn/skin/m04blueskin/image/nopic.gif -->  <!-- <script src=nnzzn/skin/m04blueskin/image/nopic.gif -->  <!-- <link rel="stylesheet" href="css/index.css"> -->  <style>    img {      width: 700px;      height: 200px;      display: block;    }  </style></head><body>      <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />    <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />    <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" />  <imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" /><imgage loading="lazy" src=nnzzn/skin/m04blueskin/image/nopic.gif alt="photo" /></body></html>

        可以看到,首次加載的個(gè)數(shù)是13個(gè),首屏一般只能放下4個(gè)左右,13個(gè)以后的img滾動(dòng)到視線內(nèi)部會(huì)自動(dòng)去加載。

        實(shí)踐發(fā)現(xiàn)有以下幾個(gè)特點(diǎn):

        1. Lazy loading加載數(shù)量與屏幕高度有關(guān),高度越小加載數(shù)量越少,但并不是線性關(guān)系。
        2. Lazy loading加載數(shù)量與網(wǎng)速有關(guān),網(wǎng)速越慢,加載數(shù)量越多,但并不是線性關(guān)系。
        3. Lazy loading加載沒(méi)有緩沖,滾動(dòng)即會(huì)觸發(fā)新的圖片資源加載。
        4. Lazy loading加載在窗口resize尺寸變化時(shí)候也會(huì)觸發(fā),例如屏幕高度從小變大的時(shí)候。
        5. Lazy loading加載也有可能會(huì)先加載后面的圖片資源,例如頁(yè)面加載時(shí)滾動(dòng)高度很高的時(shí)候。

        與Javascript有關(guān)的幾個(gè)行為特征:

        1. 判斷瀏覽器是否支持原生loading,最好使用'loading' in XXX判斷。
        2. 獲取loading屬性值可以直接img.loading;
        3. 原生loading不可寫(xiě),不可訪問(wèn)例如HTMLImageElement.prototype.loading會(huì)報(bào)錯(cuò)Illegal invocation。
        4. 如果要使用,注意做兼容性處理。
      4.  
        (文/企資小編)
        打賞
        免責(zé)聲明
        本文為企資小編推薦作品?作者: 企資小編。歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明原文出處:http://m.sneakeraddict.net/news/show-172435.html 。本文僅代表作者個(gè)人觀點(diǎn),本站未對(duì)其內(nèi)容進(jìn)行核實(shí),請(qǐng)讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,作者需自行承擔(dān)相應(yīng)責(zé)任。涉及到版權(quán)或其他問(wèn)題,請(qǐng)及時(shí)聯(lián)系我們郵件:weilaitui@qq.com。
         

        Copyright ? 2016 - 2023 - 企資網(wǎng) 48903.COM All Rights Reserved 粵公網(wǎng)安備 44030702000589號(hào)

        粵ICP備16078936號(hào)

        微信

        關(guān)注
        微信

        微信二維碼

        WAP二維碼

        客服

        聯(lián)系
        客服

        聯(lián)系客服:

        在線QQ: 303377504

        客服電話: 020-82301567

        E_mail郵箱: weilaitui@qq.com

        微信公眾號(hào): weishitui

        客服001 客服002 客服003

        工作時(shí)間:

        周一至周五: 09:00 - 18:00

        反饋

        用戶
        反饋

        中文字幕久久精品无码| 中文字幕av一区| 无码中文字幕日韩专区| 国产在线拍偷自揄拍无码| 久久Av无码精品人妻系列| 中文字幕乱码人妻无码久久| 高潮潮喷奶水飞溅视频无码| 免费无码国产V片在线观看| 日韩乱码人妻无码中文字幕久久 | 亚洲美日韩Av中文字幕无码久久久妻妇 | 最新中文字幕AV无码不卡| 久久久久成人精品无码| 中文字幕无码久久精品青草| av无码国产在线看免费网站| 天堂а√在线地址中文在线| 国产∨亚洲V天堂无码久久久| 最近中文字幕完整在线看一 | 中文字幕久久亚洲一区| 一本大道久久东京热无码AV| 中文字幕有码无码AV| 中出人妻中文字幕无码| 午夜不卡久久精品无码免费 | 天堂AV无码AV一区二区三区 | 中文字幕无码一区二区三区本日| 国产福利电影一区二区三区久久老子无码午夜伦不 | 无码精品A∨在线观看| 亚洲国产日韩欧美在线a乱码日本中文字幕高清 | 免费AV一区二区三区无码| 亚洲av无码精品网站| 中文字幕欧美日韩| 亚洲va中文字幕无码| 国产精品多人p群无码| 亚洲级αV无码毛片久久精品| 最近更新中文字幕第一页| 亚洲精品无码你懂的网站| 东京热加勒比无码少妇| 亚洲成a人片在线观看无码| 亚洲国产日韩欧美在线a乱码日本中文字幕高清 | 精品久久久无码人妻中文字幕豆芽| 日韩精品无码一区二区三区不卡 | 无码人妻AV一二区二区三区|