【问题标题】:How to make loading screen run until all image are loaded?如何使加载屏幕运行直到所有图像都加载完毕?
【发布时间】:2021-03-16 11:13:14
【问题描述】:

我尝试在等待所有图像完全加载时制作加载屏幕。 React 生命周期是 Render -> 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 时的问题/

【问题讨论】:

  • 你为什么在const ie = [document.querySelectorAll('img')];中加上[]
  • @ShivamJha 因为如果我没有使用[ ] 包围,则地图将不起作用(即,如果我输入[ ],则成为数组),我试图删除它之前和TypeError: ie.map is not a function 显示。

标签: javascript reactjs jsx


【解决方案1】:

也许这个例子可以帮助你。但请记住,这仅适用于未嵌套在组件内的图像。

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>

【讨论】:

  • 天啊,我用的是arrayfrom。 document.images 之前...然后是地图,然后是 onload。我以前没想过使用filter..谢谢,兄弟,你救了我的一天.....我得到的最简单的解决方案......
【解决方案2】:

反应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;

【讨论】:

    【解决方案3】:

    最好的办法是创建一个 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会在加载图片时更新images状态数组中图片的hasLoaded属性。然后,您可以在(在这种情况下)imagesLoading 为真时有条件地渲染加载屏幕,因为我有条件地渲染了“图像正在加载”文本。

    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
      }
    ];
    

    【讨论】:

      猜你喜欢
      • 2011-06-14
      • 1970-01-01
      • 2023-03-31
      • 2019-02-24
      • 2017-07-20
      • 2012-03-21
      • 2011-09-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多