如何延迟加载内联样式 属性 (React) 中的背景图像?

How to Lazy load the background image inside the inline style property (React)?

我目前正在开发我的第一个 React 应用程序,我正面临一些困难(对我来说)。

<div
    className="container-fluid"
    id="cityDetail"
    style={{
        backgroundImage: `url(${camera.lastPhoto})`,
        backgroundRepeat: "no-repeat",
        backgroundPosition: "center",
        backgroundSize: "cover",
        height: "100vh"
    }}
>

我想延迟加载背景图片。

我还没有找到 components/utilities 这样做的好处。 有人有什么想法吗?

这是一个用于延迟加载图像的简单组件:

class LazyBackground extends React.Component {
  state = { src: null };

  componentDidMount() {
    const { src } = this.props;

    const imageLoader = new Image();
    imageLoader.src = src;

    imageLoader.onload = () => {
      this.setState({ src });
    };
  }

  render() {
    return <div {...this.props} style={{ backgroundImage: `url(${this.state.src || this.props.placeholder})` }} />;
  }
}

你可以用 <LazyBackground src='path/to/hd.jpg' placeholder='path/to/placeholder.jpg' />

来称呼它

这是一个基于 Naoise 回答的自定义 React 钩子:

const useProgressiveImage = src => {  
  const [sourceLoaded, setSourceLoaded] = useState(null)

  useEffect(() => {
    const img = new Image()
    img.src = src
    img.onload = () => setSourceLoaded(src)
  }, [src])

  return sourceLoaded 
}

用法:

const Component = (source, placeholder) => {
  const loaded = useProgressiveImage(source)

  return (
    <div style={{ backgroundImage: `url(${loaded || placeholder})` }} />
  )
}

像这样的功能组件:

function LazyBackground({src}) {
    const [source, setSource] = useState("preload.jpg")

    useEffect(() => {
        const img = new Image()
        img.src = src
        img.onload = () => setSource(src)
    }, [src])

    return(
        <div style={{backgroundImage: `url(${source})`}}></div>
    )
}

用法:

<LazyBackground src={"https://example.com/your_image.jpg"}/>

为了延迟加载 background-image,您将需要为 CSS 属性创建一个样式表来加载带有 url 的任何文件,因为您不需要这些图像延迟第一次内容丰富​​的绘画。 例如:

FirstModal.module.less

This file has the vital CSS properties that will be loaded first...

.styles {
    &-container {
        position: absolute;
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-content: center;
        justify-content: center;
        align-items: center;
    }
}

firstModalBackground.module.less

This file will load after the critical CSS...

.styles {
    &-container {
        background: url('../../images/code/code.jpg') no-repeat center center fixed;
        background-size: cover;
    }
}

出于演示目的,我将在此处使用 React.Component,但是,如果您想尝试优化某些东西,您也可以使用 React.PureComponent(我测试过,一切正常)。

firstModal.jsx

const classNames = require('classnames');
const React = require('react)';
const {stylesContainer} = require('./firstModal.module.less');

class FirstModal extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            classNames: classNames([stylesContainer])
        };
    }

    async componentDidMount() {
        const backgroundImage = await import(
            './firstModalBackground.module.less'
        );
        this.setState({
            classNames: [
                classNames(this.state.classNames, [backgroundImage.stylesContainer]),
            ]
        });
    }

    render() {
        // console.log(this.state.classNames);
        return <div className={this.state.classNames}>It werks!</div>;
    }
}

module.exports = FirstModal;

你甚至可以更进一步,如果你有一个加载速度更快的低分辨率图像,你可以有一个“三步背景图像加载”,例如,在 componentDidMount:

    async componentDidMount() {
        const lowResolutionBackgroundImage = await import(
            '../greeting-page/firstModalLowResBackground.module.less'
        );
        const baseClass = this.state.classNames;
        this.setState({
            classNames: [
                classNames(baseclass,
                    lowResolutionBackgroundImage.stylesContainer),
                ]
            });
        const backgroundImage = await import(
            './firstModalBackground.module.less'
        );
        this.setState({
            classNames: [
                classNames(baseClass,
                    backgroundImage.stylesContainer),
            ]
        });
    }

对于延迟加载图像,有组件用于它,但我不确定它是否适用于背景图像。无论如何 react-lazy-load-image-componen 你可以安装 纱线或 npm 如下所示:

npm i --save react-lazy-load-image-component

yarn add react-lazy-load-image-component

然后你需要在你的 React 应用中导入它:

import React from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
 
const MyImage = ({ image }) => (
  <div>
    <LazyLoadImage
      alt={image.alt}
      height={image.height}
      src={image.src} // use normal <img> attributes as props
      width={image.width} />
    <span>{image.caption}</span>
  </div>
);
 
export default MyImage;

对于其中的道具,你可以看到这个 link: https://www.npmjs.com/package/react-lazy-load-image-component

import { LazyLoadComponent } from 'react-lazy-load-image-component';

...

<LazyLoadComponent id={key_id}>
   <div style={{ backgroundImage: `url(${src})` }} />
</LazyLoadComponent>