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

标签 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 被执行。我们如何在延迟加载图像的情况下实现它。

最佳答案

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

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>

关于javascript - 使用样式化组件实现图像延迟加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58352168/

相关文章:

javascript - angularjs对话框表单数据不更新范围

javascript - 如何在页面调整大小时保持 div 可见?

javascript - Angular-ui 示例中的 Angular 链接函数 iElement Magic

css - 无法单击具有负 z-index 的文本框

node.js - 我无法从我的 REACT 应用程序的 azure 应用程序服务配置中读取环境变量

reactjs - navigation.goback() 缺少数据

javascript - 粘性滚动条在到达页面顶部时改变高度

html - 设置 Angular Material Tooltip 的位置

css - 基于 JavaFX CSS 类型的选择器

javascript - 如何在渲染之外将 Prop 从一个组件发送到另一个组件?