使用样式化组件实现图像的延迟加载

时间:2019-10-12 08:10:42

标签: javascript css reactjs

我们正在使用样式化的组件在屏幕上渲染图像。我试图实现的是,图像应该以惰性方式加载,首先加载分辨率较低的图像,然后加载高分辨率的图像。 这就是我想要做的。

const Imagephone = styled.div`
  // width: 25.5rem;
  // width: 21rem;
  width: 23.75rem;
  height: 48.230rem;
  margin: 0 auto;
  background: ${props => props.primary ? "palevioletred" : "white"};
  background-image: url(${props => !props.loaded || props.error ?
  `https://some url`:
    `https://some url2`
  }) ;


  background-repeat: no-repeat;
  background-size: cover;
  position: relative;
  top: ;`


在我班上,我有这个

    super(props);
    this.state = {
      loaded: false,
      error: false
    };
  }

  componentDidMount() {
    const img = new Image();
    debugger
    img.onload = () => {
      debugger
      this.setState({
        loaded: true
      });
      debugger
    };
    img.onerror = () => {
      this.setState({
        error: true
      });
    };

  }```
and in my render i am doing this .
     <Imagephone loaded={this.state.loaded} error={this.state.error} />

` 我担心的是,在挂载组件并加载了映像之后,我们需要将加载状态设置为true,但此部分不会执行。 我没有看到img.onload被执行。如果延迟加载图片,我们应该如何实现。

2 个答案:

答案 0 :(得分:1)

问题在于您正在创建一个新的Image实例,并依赖于它的onloadonerror方法。但是,您需要使用渲染的img的元素onLoadonError道具。

const LazyImage = ({ loadingSrc, actualSrc, errorSrc, ...props }) => {
  const [isImageLoaded, setImageLoaded] = React.useState(false);
  const [hasError, setHasError] = React.useState(false);
  
  const src = React.useMemo(() => {
    if (hasError) {
      return errorSrc;
    }
    
    if (isImageLoaded) {
      return actualSrc;
    }
    
    return loadingSrc;
  }, [hasError, isImageLoaded])
  
  return (
    <img
      src={src}
      onLoad={() => setImageLoaded(true)}
      onError={() => setHasError(true)}
      {...props}
    />
  )
}

const App = () => (
  <LazyImage
    loadingSrc="https://media3.giphy.com/media/17mNCcKU1mJlrbXodo/giphy.gif"
    actualSrc="https://hackernoon.com/hn-images/1*y6C4nSvy2Woe0m7bWEn4BA.png"
    errorSrc="https://kuwaitlifestyleblog.files.wordpress.com/2016/07/windows_bug6-100581894-primary-idge.jpg?w=608&h=405"
    width={300}
    style={{ margin: '0 auto', display: 'block' }}
  />
)

ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

<div id="root"></div>

编辑:

使用styled-components

const StyledImage = styled.div`
  background-image: url("${props => props.error ? props.errorSrc : (props.loading ? props.loadingSrc : props.actualSrc)}");
  background-position: center center;
  background-size: contain;
  width: 300px;
  height: 200px;
  display: block;
  margin: 0 auto;
`;

const LazyImage = ({ loadingSrc, actualSrc, errorSrc, ...props }) => {
  const [isImageLoaded, setImageLoaded] = React.useState(false);
  const [hasError, setHasError] = React.useState(false);
  
  React.useEffect(() => {
    const img = new Image();
    
    img.onload = () => setImageLoaded(true);
    img.onerror = () => setHasError(true);

    img.src = actualSrc;
  }, [actualSrc])
  
  return (
    <StyledImage
      loadingSrc={loadingSrc}
      actualSrc={actualSrc}
      errorSrc={actualSrc}
      loading={!isImageLoaded}
      error={hasError}
      {...props}
    />
  )
}

const App = () => (
  <LazyImage
    loadingSrc="https://media3.giphy.com/media/17mNCcKU1mJlrbXodo/giphy.gif"
    actualSrc="https://hackernoon.com/hn-images/1*y6C4nSvy2Woe0m7bWEn4BA.png"
    errorSrc="https://kuwaitlifestyleblog.files.wordpress.com/2016/07/windows_bug6-100581894-primary-idge.jpg?w=608&h=405"
  />
)

ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>

<div id="root"></div>

答案 1 :(得分:0)

您的图片需要一个src才能加载某些内容:

  componentDidMount() {
    const img = new Image();
    debugger
    img.onload = () => {
      debugger
      this.setState({
        loaded: true
      });
      debugger
    };
    img.onerror = () => {
      this.setState({
        error: true
      });
    };
    // This line will fire a request for the image file
    img.src = this.props.imgSrc
  }

然后

  background-image: url(${props => !props.loaded || props.error
   ? `https://fallback.url`
   : props.imgSrc
  });