react 實(shí)現(xiàn)圖片正在加載中 加載完成 加載失敗三個(gè)階段的原理解析
最近博客寫(xiě)道項(xiàng)目列表中,發(fā)現(xiàn)這里比較多圖片,一開(kāi)加載會(huì)比較慢,然后就想要用一個(gè)loading的圖片來(lái)占位。與此同時(shí),如果圖片加載失敗那么顯示錯(cuò)誤的圖片,不顯示一個(gè)原有的錯(cuò)誤,那樣比較難看。
效果

原理解析
這個(gè)就是一個(gè)組件,一個(gè)圖片展示的組件,直接更改img標(biāo)簽的url地址就好,對(duì)的,是這樣的,在vue中直接更改地址,vue會(huì)有響應(yīng)式的更新數(shù)據(jù)。
圖片的事件
圖片是有許多的事件的,例如,onload, onerror等,圖片只要一加載就會(huì)調(diào)用onload的事件,不管是加載成功還是加載失敗都會(huì)調(diào)用這個(gè)方法。而onerror方法是圖片在沒(méi)有顯示出來(lái)就會(huì)調(diào)用這個(gè)方法。從這兩個(gè)方法對(duì)比可以得知,我們需要使用onload來(lái)一開(kāi)始加載圖片,并且圖片可以成功,可以失敗等。
組件代碼
import { ImgHTMLAttributes } from "react";
/**
* 圖片占位組件屬性
*/
export interface IImagProps<T> extends ImgHTMLAttributes<T> {
/**
* 加載中的圖片
*/
loadingImg?: string,
/**
* 失敗加載的圖片
*/
errorImg?: string,
/**
* 圖片正常顯示的地址
*/
src: string,
}
import React, { useState } from 'react'
// 下面這兩個(gè)是導(dǎo)入默認(rèn)的圖片
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)
// 是否第一次加載,如果不使用這個(gè)會(huì)加載兩次
const [isFlag, setIsFlag] = useState(false)
/**
* 圖片加載完成
*/
const handleOnLoad = () => {
// 判斷是否第一次加載
if (isFlag) return;
// 創(chuàng)建一個(gè)img標(biāo)簽
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>
</>
)
}
// 設(shè)置默認(rèn)的圖片加載中的樣式和失敗的圖片
Img.defaultProps = {
loadingImg: loadImg,
errorImg: errorImg
}
PS:下面看下React中img圖片加載完成前的loading效果
- 我在React中有這么一個(gè)需求,那就是我希望在圖片加載完成前的時(shí)候一直顯示loading動(dòng)畫(huà)效果,等圖片加載完成了就實(shí)現(xiàn)圖片的渲染
- 先講講具體的思路,再來(lái)說(shuō)說(shuō)實(shí)際的應(yīng)用
- 實(shí)現(xiàn)思路:
// 假設(shè)我要加載這三張網(wǎng)頁(yè)圖片
var imglist = ['http://example.com/demo1.png','http://example.com/demo2.png','http://example.com/demo3.png']
// images 使用用來(lái)存儲(chǔ) 加載完成的圖片的
var images = []
imglist.forEach(el=>{
var image = new Image()
image.src = el
image.onload = function(){
// 說(shuō)明圖片image加載完成了
// 將加載完成的image添加到images中
images.push(image)
}
})
// 在組件渲染的時(shí)候進(jìn)行判斷
if(images.length === 3){
// 說(shuō)明此時(shí)三張網(wǎng)頁(yè)圖片已經(jīng)全部加載完成了,可以進(jìn)行渲染了
// 渲染加載完成的圖片
}else{
// 說(shuō)明此時(shí)網(wǎng)頁(yè)圖片還沒(méi)有全部加載完成,這時(shí)候接著loadding動(dòng)畫(huà)效果
// loadding動(dòng)畫(huà)效果
}
具體實(shí)現(xiàn)的例子
import React from 'react'
import { Carousel, Spin } from 'antd' // 使用antd
// 創(chuàng)建 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(){
// 在渲染之前進(jìn)行操作
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){
// 說(shuō)明三張圖片已經(jīng)全部加載完成,這個(gè)時(shí)候已經(jīng)可以渲染圖片了
return (
<div className='common-body'>
<Carousel autoplay>
{imglist.map(el=>(
<img src={el.src} key={el.id} alt={el.alt} />
))}
</Carousel>
</div>
)
}else{
// 說(shuō)明圖片還沒(méi)有全部加載完成,這個(gè)時(shí)候要顯示loading動(dòng)畫(huà)效果
return (
<div className='common-loading'>
<Spin tip='Loading...' size='large'></Spin>
</div>
)
}
}
}
export default Home
這個(gè)方法還是比較好用的
以上就是react 實(shí)現(xiàn)圖片正在加載中 加載完成 加載失敗三個(gè)階段的原理解析的詳細(xì)內(nèi)容,更多關(guān)于react圖片加載完成的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React的特征單向數(shù)據(jù)流學(xué)習(xí)
這篇文章主要為大家介紹了React的特征單向數(shù)據(jù)流學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
React Hook 'useEffect' is call
這篇文章主要為大家介紹了React Hook 'useEffect' is called in function報(bào)錯(cuò)解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
React?Native性能優(yōu)化指南及問(wèn)題小結(jié)
本文將介紹在React?Native開(kāi)發(fā)中常見(jiàn)的性能優(yōu)化問(wèn)題和解決方案,包括ScrollView內(nèi)無(wú)法滑動(dòng)、熱更新導(dǎo)致的文件引用問(wèn)題、高度獲取、強(qiáng)制橫屏UI適配、低版本RN適配iOS14、緩存清理、navigation參數(shù)取值等,感興趣的朋友一起看看吧2024-01-01
在react項(xiàng)目中使用antd的form組件,動(dòng)態(tài)設(shè)置input框的值
這篇文章主要介紹了在react項(xiàng)目中使用antd的form組件,動(dòng)態(tài)設(shè)置input框的值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
使用react和redux構(gòu)建一個(gè)簡(jiǎn)單的計(jì)數(shù)器
這篇文章主要為大家詳細(xì)介紹了如何使用react和redux構(gòu)建一個(gè)簡(jiǎn)單的計(jì)數(shù)器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-01-01
react-pdf?打造在線簡(jiǎn)歷生成器的示例代碼
本文主要介紹了react-pdf?打造在線簡(jiǎn)歷生成器的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

