如何使加载屏幕一直运行到加载完所有图像



我试图在等待所有图像完全加载的同时制作一个加载屏幕。React生命周期是渲染->componentDidMount->渲染,我的图像没有完全加载,只是被调用了,但我的componentDidMount总是完成并执行渲染,即使我的图像还没有完全加载。

componentDidMount() {
const ie = [document.querySelectorAll('img')];
ie.map(imgElm => {
for (const img of imgElm) {
if (!img.complete) {
this.setState({ imageIsReady : true});
}
}
return this.setState({ imageIsReady : false});
})
}

componentDidMountfor循环函数上,试着检查每个img是否完整,给我一百个true(我的图像很多,只是试着制作图库(。加载屏幕显示,但只有几毫秒,然后我可以滚动我的图像,但超过一半的图像仍在加载。

render() {
<div>
{
this.state.imageIsReady ?
<div className='inset-0 fixed flex justify-center z-20 w-full h-full bg-black bg-opacity-25 blur'>
<img src={loading} className='w-3/12' alt="load"/>
</div> :
<div className='hidden '>
<img src={loading} alt="load"/>
</div>
}
<div>page......</div>
</div>
}

我的代码:https://alfianahar.github.io/MobileLegendHeroList/在这个网站上,我在我的componentDidMount上使用setTimeout,这并不能解决我在使用慢速3g和快速3g/时的问题

也许这个例子可以帮助你。但请记住,这只适用于并没有嵌套在组件中的图像。

class Component extends Component {
constructor(props) {
super(props)
this.state = {
ready: false
}
}
componentDidMount() { 
Promise.all(
Array.from(document.images)
.filter(img => !img.complete)
.map(img => new Promise(
resolve => { img.onload = img.onerror = resolve; }
))).then(() => {
this.setState({ ready: true })
});
}

render() {
if ( ! this.state.ready ) return <div>Loader</div>
return <div>Content</div>
}
}
<Container>
<img/> <!-- work -->
<Component>
<img/> <!-- doesn't work -->
</Component>
</Container>

反应16.8.x

import React from "react";
function App() {
const [imagesRequested, setImagesRequested] = React.useState({});
const [images, setImages] = React.useState([
{ name: "first image", src: "https://picsum.photos/200/300" },
{ name: "second image", src: "https://picsum.photos/300/300" }
]);
return (
<React.Fragment>
{images.map((currentImage) => (
<React.Fragment>
{!imagesRequested[currentImage.name] && <div>loading...</div>}
<img
style={{ opacity: imagesRequested[currentImage.name] ? 1 : 0 }}
src={currentImage.src}
onLoad={() => {
setTimeout(() => { // Fake server latency (2 seconds for per image)
setImagesRequested((previousState) => ({
...previousState,
[currentImage.name]: true
}));
}, 2000);
}}
/>
</React.Fragment>
))}
</React.Fragment>
);
}
export default App;

您最好的选择是创建一个LoadableImage组件,然后该组件将处理对象的onLoad事件。然后,这个onLoad事件可以调用父回调函数来设置其加载状态。

LoadableImage.js

import { useState } from "react";
const LoadableImage = (props) => {
const { src, alt, width, height, onLoad, onError, id } = props;
//you can use this to render a custom broken image of some sort
const [hasError, setHasError] = useState(false);
const onLoadHandler = () => {
if (typeof onLoad === "function") {
onLoad(id);
}
};
const onErrorHandler = () => {
setHasError(true);
if (typeof onError === "function") {
onError(id);
}
};
return (
<img
src={src}
alt={alt}
width={width}
height={height}
onLoad={onLoadHandler}
onError={onErrorHandler}
/>
);
};
export default LoadableImage;

现在,您可以处理实现中的回调并采取适当的操作。您可以保持所有图像的状态,以及它们的加载状态。

App.js

export default function App() {
const [images, setImages] = useState(imageList);
const imagesLoading = images.some((img) => img.hasLoaded === false);
const handleImageLoaded = (id) => {
setImages((prevState) => {
const index = prevState.findIndex((img) => img.id === id);
const newState = [...prevState];
const newImage = { ...newState[index] };
newImage.hasLoaded = true;
newState[index] = newImage;
return newState;
});
};
return (
<div className="App">
{imagesLoading && <h2>Images are loading!</h2>}
{images.map((img) => (
<LoadableImage
key={img.id}
id={img.id}
src={img.src}
onLoad={handleImageLoaded}
/>
))}
</div>
);
}

这里handleImageLoaded将在加载图像时更新图像状态数组中图像的hasLoaded属性。然后,当(在这种情况下(imagesLoading为true时,您可以有条件地渲染加载屏幕,因为我已经有条件地rend了";Imags正在加载";文本

Codesandbox

imageList看起来像这个

const imageList = [
{
id: 1,
src:
"https://images.unsplash.com/photo-1516912481808-3406841bd33c?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=683&q=80",
hasLoaded: false
},
{
id: 2,
src: "https://via.placeholder.com/150",
hasLoaded: false
},
{
id: 3,
src: "https://via.placeholder.com/151",
hasLoaded: false
}
];

最新更新