自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

20行代碼,封裝一個 React 圖片懶加載組件

開發(fā) 前端
圖片懶加載是我們在做性能優(yōu)化時非常重要的手段。我們常常需要圖片在進入頁面可視區(qū)域時,才讓加載圖片的行為發(fā)生。

一、如何判斷圖片進入視口

我們可以使用傳統(tǒng)的方式,監(jiān)聽頁面的 scroll 事件,然后調(diào)用目標函數(shù)的 getBoundingClientRect 方法,得到目標元素在網(wǎng)頁中的位置信息。

但是我并不喜歡監(jiān)聽 scroll 事件。因為他會大量的執(zhí)行,并且 getBoundingClientRect 是一個同步方法,都在主線程上運行,當其頻繁執(zhí)行時可能會導致性能出現(xiàn)問題。

我們可以使用另外一種方式來做到同樣的效果。他就是 IntersectionObserver。

var observer = new IntersectionObserver(callback[, option])

IntersectionObserver 提供了一種異步觀察目標元素與其祖先元素或者頂級文檔 viewport 交叉狀態(tài)的方法。其祖先元素或者視口,被稱為根 root。當目標元素與根元素在視圖上產(chǎn)生交集時,回調(diào)函數(shù)就會執(zhí)行。

我們也可以在 options 中,自定義配置 root 元素。

let options = {
  root: document.querySelector("#scrollArea"),
  rootMargin: "0px",
  threshold: 1.0,
};

let observer = new IntersectionObserver(callback, options);

options 接受三個參數(shù)。

root

自定義目標元素的根節(jié)點。該節(jié)點必須是目標元素的祖先元素。如果未指定,默認為視口。

rootMargin

根元素周圍的邊距。其值可以類似于 CSS 的 margin 屬性,例如 10px 20px 30px 40px,以此表示上、右、下、左。這些值夜可以是百分比。在計算交叉點之前,這組值用于增大或者縮小根元素邊框的每一側,默認為 0。

threshold

一個數(shù)字或者一組數(shù)字。表示目標可見度達到多少百分比時,回調(diào)函數(shù)就應該執(zhí)行。例如,如果我希望交叉部分每超過目標元素 25% 就執(zhí)行,那么我就傳入 [0, 0.25, 0.5, 0.75, 1]. 默認值為 0。

創(chuàng)建的實例有 4 個方法可以讓我們使用。

  • observer.disconnect() 停止監(jiān)聽。
  • observer.observe(element) 開始監(jiān)聽目標元素。
  • observer.takRecords() 返回所有目標元素的信息對象數(shù)組。
  • observer.unobserve(element)停止監(jiān)聽目標元素。

回調(diào)函數(shù)執(zhí)行時,接收一個參數(shù),該參數(shù)為回調(diào)函數(shù)提供目標對象的位置信息,一共有六個屬性。

{
  // 回調(diào)執(zhí)行的時間
  time: 3893.92,
  
  // 被觀察的目標對象
  target: element
  
  // 根元素位置信息
  rootBounds: ClientRect {
    bottom: 920,
    height: 1024,
    left: 0,
    right: 1024,
    top: 0,
    width: 920
  },
  
  // 目標元素位置信息
  boundingClientRect: ClientRect {
     // ...
  },
  
  // 交叉區(qū)域矩形的位置大小信息
  intersectionRect: ClientRect {
    // ...
  },
  
  // 元素可見度比例
  intersectionRatio: 0.54,
}

該參數(shù)返回一個數(shù)組包含一個或者多個元素的位置信息。

二、圖片懶加載原理

在瀏覽器中,展示一張圖片,我們使用的是 img 標簽。img 標簽有一個必須傳入的屬性 src,當我們不傳入 src 時,圖片無法加載,一旦傳入 src,那么圖片就會立即開始加載。

因此,我們需要做的事情就是,當圖片沒有出現(xiàn)在可視區(qū)域時,不傳入正確的 src 屬性,當通過上述的方法判斷圖片已經(jīng)出現(xiàn)在可視區(qū)域,我們就傳入正確的 src,此時圖片會立即加載。

三、代碼實現(xiàn)

首先,我們封裝的新組件,一定要繼承原有 img 標簽的所有能力。先定義一個 Props 類型聲明,目前我們并不需要擴展其他的屬性,暫時先這樣,未來會根據(jù)需求的變動逐漸新增新的屬性值。

interface LazyLoadProps extends DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {
  
}

然后我們我要的事情是,除了 src 屬性,我們要把其他屬性全部直接傳給 img 標簽,具體方式如下:

export default function LazyLoad(props: LazyLoadProps) {
  const {src = '', ...other} = props
  
  return (
    <img {...other} />
  )
}

然后我們需要定義一個 ref 屬性,用于獲取 img 標簽的元素對象。

export default function LazyLoad(props: LazyLoadProps) {
  const {src = '', ...other} = props
  const img = useRef(null)

  return (
    <img ref={img} {...other} />
  )
}

準備工作做好之后,我們最后只需要借助 useEffect 聲明 IntersectionObserver 實例然后監(jiān)聽圖片元素即可。

export default function LazyLoad(props: LazyLoadProps) {
  const {src = '', ...other} = props
  const [URL, setURL] = useState('')
  const img = useRef(null)

  useEffect(() => {
    var io = new IntersectionObserver((entries) => {
      // @ts-ignore
      if (entries[0].intersectionRatio > 0) {
        setURL(src)
        img.current && io.unobserve(img.current)
      }
    }, {})   

    if (img.current) {
      io.observe(img.current)
    }
  }, [])
  return (
    <img ref={img} src={URL} {...other} />
  )
}

這樣,一個滿足基本要求的圖片懶加載組件就封裝好了。

四、擴展思考

在我們做首屏優(yōu)化的時候,為了能夠達到最快的速度渲染頁面,圖片的加載往往也需要延后,但是又不能延后太多。因此此時的問題是,圖片已經(jīng)出現(xiàn)在可視區(qū)域了,我們又應該如何做才能做到懶加載呢?

在實踐中可能還會遇到的需求變動是,給圖片添加一個占位符。然后占位符元素與圖片元素的切換不是立即發(fā)生的,而是要等到我們確保圖片已經(jīng)全部加載完成之后才發(fā)生的,否則的話,可能會出現(xiàn)圖片只加載了一小半的視圖情況。這又應該如何實現(xiàn)

繼續(xù)優(yōu)化。我們希望占位符元素與圖片元素的切換沒那么生硬,而是結合動畫漸入漸出,又該如何實現(xiàn)。

繼續(xù)優(yōu)化,我們希望支持傳入 aspectFill 等屬性,確保圖片的縮放比例,不能因為寬高的設置導致圖片比例變形,又該如何實現(xiàn)

這些思考就留給大家在實踐中去嘗試驗證了。本文就不在詳細介紹。

責任編輯:姜華 來源: 這波能反殺
相關推薦

2017-03-28 10:11:12

Webpack 2React加載

2017-03-28 21:03:35

代碼React.js

2019-07-24 16:00:37

Python代碼高清圖片

2024-11-08 17:22:22

2024-06-03 00:00:01

2020-11-18 09:30:29

圖片懶加載前端瀏覽器

2015-10-08 10:58:51

圖片懶加載

2019-04-19 14:40:15

代碼Python機器人

2017-07-19 13:27:44

前端Javascript模板引擎

2014-01-22 09:19:57

JavaScript引擎

2018-07-12 09:51:04

Python代碼對象模型

2021-06-21 15:49:39

React動效組件

2021-03-31 08:01:24

React Portareactcss3

2022-05-13 08:46:46

jsoneditorjson編輯器

2023-04-28 09:30:40

vuereact

2023-04-10 08:30:30

json編輯器typescript

2022-01-26 16:30:47

代碼虛擬機Linux

2013-03-04 10:22:30

Python

2022-06-29 09:02:31

go腳本解釋器

2021-03-19 06:31:06

vue-lazyloa圖片懶加載項目
點贊
收藏

51CTO技術棧公眾號