欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React實(shí)現(xiàn)圖片懶加載的常見(jiàn)方式

 更新時(shí)間:2024年01月09日 08:23:49   作者:Mh  
圖片懶加載是一種優(yōu)化網(wǎng)頁(yè)性能的技術(shù),它允許在用戶滾動(dòng)到圖片位置之前延遲加載圖片,通過(guò)懶加載,可以在用戶需要查看圖片時(shí)才加載圖片,避免了不必要的圖片加載,本文給大家介紹了React實(shí)現(xiàn)圖片懶加載的常見(jiàn)方式,需要的朋友可以參考下

前言

圖片懶加載是一種優(yōu)化網(wǎng)頁(yè)性能的技術(shù),它允許在用戶滾動(dòng)到圖片位置之前延遲加載圖片。通過(guò)懶加載,可以在用戶需要查看圖片時(shí)才加載圖片,避免了不必要的圖片加載,從而提高了網(wǎng)頁(yè)的加載速度和用戶體驗(yàn)。

方案一

實(shí)現(xiàn)思路

在說(shuō)明思路之前,先了解幾個(gè)常見(jiàn)的視圖屬性。

  • clientHeight:可視區(qū)域的高度,對(duì)應(yīng)的也就是下圖中的滾動(dòng)區(qū)域。
  • scrollTop:滾動(dòng)條滾動(dòng)的高度,它指的是內(nèi)容區(qū)的頂部到可視區(qū)域頂部的距離。
  • offsetTop:元素到offsetParent頂部的距離。
  • offsetParent:距離元素最近的一個(gè)具有定位的祖宗元素(relative,absolute,fixed),若祖宗都不符合條件,offsetParent為body。

圖解:

根據(jù)上面的圖解可知,當(dāng)圖片的滾動(dòng)條滾動(dòng)的高度加上可視區(qū)域的高度大于當(dāng)前的圖片的offsetTop,那么說(shuō)明圖片正在進(jìn)入可視區(qū)域。這個(gè)時(shí)候便可以加載當(dāng)前圖片。

第一步

模擬后臺(tái)返回的圖片url,遍歷產(chǎn)生一個(gè)url集合,用于后面的懶加載使用。

const imgUrls = (num = 10) => {
  const urls = [];
  for (let i = 0; i < num; i++) {
    const url = `https://robohash.org/${i}.png`;
    urls.push(url);
  }
  return urls;
};

第二步

遍歷圖片url集合,渲染100張loading圖片,css部分省略。

    <div className={styles['box-one']} ref={scrollRef}>
      {imgUrls(100).map((item) => {
        return <img data-src={item} key={item} src={loadingUrl} alt="" />;
      })}
    </div>

效果預(yù)覽

第三步

監(jiān)聽(tīng)容器的滾動(dòng)事件,當(dāng)容器滾動(dòng)時(shí)計(jì)算容器的高度加上滾動(dòng)條的高度大于當(dāng)前圖片的offsetTop時(shí)加載當(dāng)前的圖片。完整代碼如下:

import loadingUrl from '@/assets/imgs/loading.jpg';
import { useEffect, useRef } from 'react';
import styles from '../index.less';

// 圖片url
const imgUrls = (num = 10) => {
  const urls = [];
  for (let i = 0; i < num; i++) {
    const url = `https://robohash.org/${i}.png`;
    urls.push(url);
  }
  return urls;
};

const LazyLoading = () => {
  const scrollRef = useRef({} as any);

  // 滾動(dòng)事件
  const changeScroll = () => {
    const clientHeight = scrollRef?.current.clientHeight; //可視區(qū)域高度
    const scrollTop = scrollRef?.current.scrollTop; //滾動(dòng)條滾動(dòng)高度
    const childNodes = scrollRef?.current.childNodes; // 獲取所有圖片集合

    for (let j = 0; j < childNodes.length; j++) {
      const element = childNodes[j];
      if (scrollTop + clientHeight > element.offsetTop) {
        element.src = element.getAttribute('data-src'); // 替換當(dāng)前的src
      }
    }
  };

  useEffect(() => {
    changeScroll(); // 第一次渲染的時(shí)候替換loading圖片
  }, []);

  return (
    <div className={styles['box-one']} ref={scrollRef} onScroll={changeScroll}>
      {imgUrls(100).map((item) => {
        return <img data-src={item} key={item} src={loadingUrl} alt="" />;
      })}
    </div>
  );
};

export default LazyLoading;

效果預(yù)覽

方案二

實(shí)現(xiàn)思路

方案二的實(shí)現(xiàn)思路利用瀏覽器提供的 IntersectionObserver API實(shí)現(xiàn)。IntersectionObserver API提供了一種方便的方式來(lái)監(jiān)視目標(biāo)元素和其祖先元素或視窗之間的交叉狀態(tài)變化。當(dāng)目標(biāo)元素進(jìn)入或離開視口時(shí),可以觸發(fā)回調(diào)函數(shù),進(jìn)行相應(yīng)的操作。它的原理是通過(guò)注冊(cè)一個(gè)回調(diào)函數(shù)來(lái)觀察特定元素的交叉狀態(tài)變化,并在滿足條件時(shí)執(zhí)行相應(yīng)的操作。

使用 IntersectionObserver API非常簡(jiǎn)單,可以通過(guò)創(chuàng)建一個(gè) IntersectionObserver 實(shí)例,并傳入回調(diào)函數(shù)和選項(xiàng)對(duì)象來(lái)實(shí)現(xiàn)。回調(diào)函數(shù)會(huì)在目標(biāo)元素的交叉狀態(tài)發(fā)生變化時(shí)被調(diào)用,并接收一個(gè)參數(shù),包含有關(guān)交叉狀態(tài)的信息。

實(shí)現(xiàn)完整代碼

import loadingUrl from '@/assets/imgs/loading.jpg';
import styles from '../index.less';
import React, { useRef, useEffect, useState } from 'react';
// 圖片url
const imgUrls = (num = 10) => {
  const urls = [];
  for (let i = 0; i < num; i++) {
    const url = `https://robohash.org/${i}.png`;
    urls.push(url);
  }
  return urls;
};

const LazyLoadImage = ({ src, alt }) => {
  const [imageSrc, setImageSrc] = useState(loadingUrl);
  const imgRef = useRef(null as any);

  useEffect(() => {
    let observer: IntersectionObserver;
    if (imgRef.current) {
      // 創(chuàng)建IntersectionObserver實(shí)例
      observer = new IntersectionObserver(
        ([entry]) => {
          // 當(dāng)圖片進(jìn)入可視區(qū)域時(shí),設(shè)置圖片地址進(jìn)行加載
          if (entry.isIntersecting) {
            setImageSrc(src);
            observer.unobserve(imgRef.current);
          }
        },
        {
          rootMargin: '0px 0px 200px 0px', // 可視區(qū)域的上邊距設(shè)置為200px
        },
      );
      observer.observe(imgRef.current); //開始觀察目標(biāo)元素
    }
    return () => {
      if (observer && observer.unobserve) {
        observer.unobserve(imgRef.current);
      }
    };
  }, [src]);

  return <img ref={imgRef} src={imageSrc} alt={alt} />;
};

const LazyLoading = () => {
  return (
    <div className={styles['box-two']}>
      {imgUrls(100).map((item) => {
        return <LazyLoadImage src={item} alt="lazy load image" />;
      })}
    </div>
  );
};

export default LazyLoading;

實(shí)現(xiàn)效果

注意事項(xiàng)

在初始化的時(shí)候,需要給imageSrc設(shè)置一個(gè)初始化的loading地址,如果沒(méi)有的話,初始化的時(shí)候會(huì)加載多張圖片。

方案三

實(shí)現(xiàn)思路

利用react的懶加載庫(kù)react-lazyload,在使用之前需要先安裝 yarn add react-lazyload,這里介紹幾個(gè)它的常見(jiàn)屬性:

  • scrollContainer: 指定的滾動(dòng)的區(qū)域,默認(rèn)值是undefined,如果沒(méi)有指定默認(rèn)是窗口的視圖作為滾動(dòng)區(qū)域。
  • offset: 元素距離視口頂部的距離,當(dāng)達(dá)到這個(gè)距離時(shí),元素將被加載。
  • scroll: 是否監(jiān)聽(tīng)滾動(dòng)
  • height: 渲染元素的占位符的高度。
  • overflow : 如果溢出容器,延遲加載組件

代碼實(shí)現(xiàn)

因?yàn)檫@里實(shí)現(xiàn)的圖片懶加載是局部懶加載,所以需要指定 scrollContainerscrollContainer 的值DOM對(duì)象。在實(shí)現(xiàn)的過(guò)程中,同時(shí)需要設(shè)置overflow為true,以及height的值。

import react, { useRef, useEffect } from 'react';
import LazyLoad from 'react-lazyload';
import styles from '../index.less';

// 圖片url
const imgUrls = (num = 10) => {
  const urls = [];
  for (let i = 0; i < num; i++) {
    const url = `https://robohash.org/${i}.png`;
    urls.push(url);
  }
  return urls;
};

const LazyLoading = () => {
  const scrollRef = useRef({} as any);

  return (
    <div className={styles['box-three']} ref={scrollRef}>
      {imgUrls(100).map((item) => {
        return (
          <LazyLoad
            height={200}
            overflow={true}
            offset={0}
            key={item}
            scroll={true}
            scrollContainer={scrollRef.current} // DOM
          >
            <img src={item} alt="" />
          </LazyLoad>
        );
      })}
    </div>
  );
};

export default LazyLoading;

實(shí)現(xiàn)效果

以上就是React實(shí)現(xiàn)圖片懶加載的常見(jiàn)方式的詳細(xì)內(nèi)容,更多關(guān)于React圖片懶加載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 插件化機(jī)制優(yōu)雅封裝你的hook請(qǐng)求使用方式

    插件化機(jī)制優(yōu)雅封裝你的hook請(qǐng)求使用方式

    這篇文章主要為大家介紹了插件化機(jī)制優(yōu)雅封裝你的hook請(qǐng)求使用方式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 簡(jiǎn)化Cocos和Native交互利器詳解

    簡(jiǎn)化Cocos和Native交互利器詳解

    這篇文章主要為大家介紹了簡(jiǎn)化Cocos和Native交互利器詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • React實(shí)現(xiàn)虛擬滾動(dòng)的三種思路詳解

    React實(shí)現(xiàn)虛擬滾動(dòng)的三種思路詳解

    在??web??開發(fā)的過(guò)程中,或多或少都會(huì)遇到大列表渲染的場(chǎng)景,為了解決大列表造成的渲染壓力,便出現(xiàn)了虛擬滾動(dòng)技術(shù),本文主要介紹虛擬滾動(dòng)的三種思路,希望對(duì)大家有所幫助
    2024-04-04
  • react-redux及redux狀態(tài)管理工具使用詳解

    react-redux及redux狀態(tài)管理工具使用詳解

    Redux是為javascript應(yīng)用程序提供一個(gè)狀態(tài)管理工具集中的管理react中多個(gè)組件的狀態(tài)redux是專門作狀態(tài)管理的js庫(kù)(不是react插件庫(kù)可以用在其他js框架中例如vue,但是基本用在react中),這篇文章主要介紹了react-redux及redux狀態(tài)管理工具使用詳解,需要的朋友可以參考下
    2023-01-01
  • ReactNative頁(yè)面跳轉(zhuǎn)Navigator實(shí)現(xiàn)的示例代碼

    ReactNative頁(yè)面跳轉(zhuǎn)Navigator實(shí)現(xiàn)的示例代碼

    本篇文章主要介紹了ReactNative頁(yè)面跳轉(zhuǎn)Navigator實(shí)現(xiàn)的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • React使用Context與router實(shí)現(xiàn)權(quán)限路由詳細(xì)介紹

    React使用Context與router實(shí)現(xiàn)權(quán)限路由詳細(xì)介紹

    這篇文章主要介紹了React使用Context與router實(shí)現(xiàn)權(quán)限路由的詳細(xì)過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解

    React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解

    這篇文章主要介紹了React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-02-02
  • React組件通信淺析

    React組件通信淺析

    這篇文章主要介紹了React組件通信,在開發(fā)中組件通信是React中的一個(gè)重要的知識(shí)點(diǎn),本文通過(guò)實(shí)例代碼給大家講解react中常用的父子、跨組件通信的方法,需要的朋友可以參考下
    2022-12-12
  • React Native中的RefreshContorl下拉刷新使用

    React Native中的RefreshContorl下拉刷新使用

    本篇文章主要介紹了React Native中的RefreshContorl下拉刷新使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • React觸發(fā)render的實(shí)現(xiàn)方法

    React觸發(fā)render的實(shí)現(xiàn)方法

    這篇文章主要介紹了React觸發(fā)render的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評(píng)論