react 實現圖片正在加載中 加載完成 加載失敗三個階段的原理解析

最近博客寫道項目列表中,發現這裡比較多圖片,一開加載會比較慢,然後就想要用一個loading的圖片來占位。與此同時,如果圖片加載失敗那麼顯示錯誤的圖片,不顯示一個原有的錯誤,那樣比較難看。

效果

在這裡插入圖片描述

原理解析

這個就是一個組件,一個圖片展示的組件,直接更改img標簽的url地址就好,對的,是這樣的,在vue中直接更改地址,vue會有響應式的更新數據。

圖片的事件

圖片是有許多的事件的,例如,onload, onerror等,圖片隻要一加載就會調用onload的事件,不管是加載成功還是加載失敗都會調用這個方法。而onerror方法是圖片在沒有顯示出來就會調用這個方法。從這兩個方法對比可以得知,我們需要使用onload來一開始加載圖片,並且圖片可以成功,可以失敗等。

組件代碼

import { ImgHTMLAttributes } from "react";

/**
 * 圖片占位組件屬性
 */
export interface IImagProps<T> extends ImgHTMLAttributes<T> {
  /**
   * 加載中的圖片
   */
  loadingImg?: string,
  /**
   * 失敗加載的圖片
   */
  errorImg?: string,
 /**
  * 圖片正常顯示的地址
  */
  src: string,
}

import React, { useState } from 'react'
// 下面這兩個是導入默認的圖片
import loadImg from './../../../assets/imgs/loading/load.gif';
import errorImg from './../../../assets/imgs/loading/error.png'
export default function Img(props: IImagProps<any>) {
  // 圖片地址
  const [src, setSrc] = useState(props.loadingImg as string)
  // 是否第一次加載,如果不使用這個會加載兩次
  const [isFlag, setIsFlag] = useState(false)
  /**
   * 圖片加載完成
   */
  const handleOnLoad = () => {
    // 判斷是否第一次加載
    if (isFlag) return;
    // 創建一個img標簽
    const imgDom = new Image();
    imgDom.src = props.src;
    // 圖片加載完成使用正常的圖片
    imgDom.onload = function () {
      setIsFlag(true)
      setSrc(props.src)
    }
    // 圖片加載失敗使用圖片占位符
    imgDom.onerror = function () {
      setIsFlag(true)
      setSrc(props.errorImg as string)
    }
  }
  
  return (
    <>
      <img src={src}
        onLoad={handleOnLoad}
        style={{
          height: 'inherit',
        }}
      ></img>
    </>
  )
}
// 設置默認的圖片加載中的樣式和失敗的圖片
Img.defaultProps = {
  loadingImg: loadImg,
  errorImg: errorImg
}

PS:下面看下React中img圖片加載完成前的loading效果

  • 我在React中有這麼一個需求,那就是我希望在圖片加載完成前的時候一直顯示loading動畫效果,等圖片加載完成瞭就實現圖片的渲染
  • 先講講具體的思路,再來說說實際的應用
  • 實現思路:
// 假設我要加載這三張網頁圖片
var imglist = ['http://example.com/demo1.png','http://example.com/demo2.png','http://example.com/demo3.png']
// images 使用用來存儲 加載完成的圖片的
var images = []
imglist.forEach(el=>{
	var image = new Image()
	image.src = el
	image.onload = function(){
		// 說明圖片image加載完成瞭
		// 將加載完成的image添加到images中
		images.push(image)
	}
})

// 在組件渲染的時候進行判斷
if(images.length === 3){
	// 說明此時三張網頁圖片已經全部加載完成瞭,可以進行渲染瞭
	// 渲染加載完成的圖片
}else{
	// 說明此時網頁圖片還沒有全部加載完成,這時候接著loadding動畫效果
	// loadding動畫效果
}

具體實現的例子

import React from 'react'
import { Carousel, Spin } from 'antd' // 使用antd
// 創建 Home組件
class Home extends React.Component{
	constructor(props){
		super(props)
		this.state = {
			imglist: [
				{
					id: '01',
					src: 'http://example.com/demo1.png',
					alt: 'demo1'
				},
				{
					id: '02',
					src: 'http://example.com/demo2.png',
					alt: 'demo2'
				},
				{
					id: '03',
					src: 'http://example.com/demo3.png',
					alt: 'demo3'
				}
			],
			images: []
		}
	}
	UNSAFE_componentWillMount(){
		// 在渲染之前進行操作
		var { imglist } = this.state
		var images = []
		imglist.forEach(el=>{
			var image = new Image()
			image.src = el.src
			image.onload = ()=>{
				images.push(image)
				this.setState({
					images
				})
			}
		})
	}
	render(){
		var { imglist, images } = this.state
		if(images.length === 3){
			// 說明三張圖片已經全部加載完成,這個時候已經可以渲染圖片瞭
			return (
				<div className='common-body'>
					<Carousel autoplay>
						{imglist.map(el=>(
							<img src={el.src} key={el.id} alt={el.alt} />
						))}
					</Carousel>
				</div>
			)
		}else{
			// 說明圖片還沒有全部加載完成,這個時候要顯示loading動畫效果
			return (
				<div className='common-loading'>
					<Spin tip='Loading...' size='large'></Spin>
				</div>
			)
		}
	}
}
export default Home

這個方法還是比較好用的

以上就是react 實現圖片正在加載中 加載完成 加載失敗三個階段的原理解析的詳細內容,更多關於react圖片加載完成的資料請關註WalkonNet其它相關文章!

推薦閱讀: