繁体   English   中英

如何延迟加载内联样式属性(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"
    }}
>

我想延迟加载 backgroundImage。

我还没有找到好的组件/实用程序来执行此操作。 有人有什么想法吗?

这是延迟加载图像的简单组件:

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 ,您需要为加载带有url任何文件的 CSS 属性创建一个样式表,因为您不希望这些图像延迟第一次内容绘制。 例如:

FirstModal.module.less

该文件具有将首先加载的重要 CSS 属性...

.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

此文件将在关键 CSS 之后加载...

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

出于演示目的,我将在这里使用 React.Component,但是,如果您想尝试优化事物,您也可以使用 React.PureComponent(我测试过它并且一切正常)。

第一个Modal.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),
            ]
        });
    }

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

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

或者

yarn add react-lazy-load-image-component

然后你需要在你的反应应用程序中导入它:

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;

对于道具,你可以看到这个链接: 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>

下面是一个使用 GSAP 通过滚动触发器内联设置背景图像的示例。

   <LazyLoadBgImg src="http://placekeanu.com/540" className="some-css-class">
        <h1>Tristan is the best</h1>
    </LazyLoadBgImg>

组件:

import React,  { useEffect, useRef, useState } from "react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
    
const LazyLoadBgImg = ({src, className, children}) => {

    const lazyLoadRef = useRef();
    const [loadImage, setLoadImage] = useState(false);

    useEffect(() => {
        ScrollTrigger.create({
            trigger: lazyLoadRef.current,
            start: "top bottom",
            onEnter: () => setLoadImage(true), 
        });      
    }, []);

    return (
        <div ref={lazyLoadRef} className={className} style={{backgroundImage: (loadImage ? "url(" + src  + ")" : '')}}>
            {children}
        </div>
    )
}

export default LazyLoadBgImg;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM