将背景图像设置为React中的属性

9

我有一个React组件需要从父级Play组件中获取背景图像,而不是在样式表中设置。 我正在尝试将其作为prop传递给组件,但不太确定如何让它起作用:

主要组件

import React from 'react'
import ReactDOM from 'react-dom'
import DeviceBlock from '/DeviceBlock/DeviceBlock'

const Play = {
  init() {
    const container = document.getElementById('blocker-container');
    if(container) {
      ReactDOM.render(
        <DeviceBlock
        backgroundImage={'background-image-url.png'}
        logo={'url-to-logo.png'} />,
        container
      )
    }
  }
}

document.addEventListener('DOMContentLoaded', () => {
  Play.init()
})

阻塞组件导入到上面的Play组件中

import React from 'react'
import './DeviceBlock.scss'

function DeviceBlock (props) {
  constructor(props) {
    super(props)
    this.state = {
      backgroundImage: backgroundImage,
      logo: logo;
    }
  }
  return (
    <div className='device-blocking' style={this.state.backgroundImage}>
      <div className='container'>
        <div className='logo'>
          <img src='{{this.state.logo}}' />
        </div>
        <div className='message'>
          <h1>Content</h1>
          <a href='/' className='btn btn--primary btn--lg'>Link</a>
        </div>
      </div>
    </div>
  )
}

export default DeviceBlock
3个回答

16
你应该 导入 背景图片。
import BackgroundImage from '...png'; // Relative Path to BackgroundImage
import Logo from '...png'; // Relative Path to Logo

并且在你的状态中

this.state = {
  backgroundImage: `url(${BackgroundImage})`,
  logo: Logo
};

我注意到你的 <img> 有误。

<img src='{{this.state.logo}}' />

应该是

<img src={this.state.logo} />

同时请注意,我看到你在一个函数内部添加了构造函数。如果你想创建一个带状态的React组件,需要将组件定义为类。

class DeviceBlock extends React.Component { 
  constructor(props) {
    super(props);
    this.state = {}
  }
  render() { 
    ...
  }
}

编辑:这是基于通过props传递的更新代码。

import React from 'react'
import ReactDOM from 'react-dom'
import DeviceBlock from '/DeviceBlock/DeviceBlock'
import BackgroundImage from '../url-to-background.png'; // Path to BackgroundImage
import Logo from 'url-to-logo.png'; // Relative Path to Logo

const Play = {
  init() {
    const container = document.getElementById('blocker-container');
    if (container) {
      ReactDOM.render(
        <DeviceBlock
          backgroundImage={BackgroundImage}
          logo={Logo} 
        />,
        container
      )
    }
  }
}

document.addEventListener('DOMContentLoaded', () => {
  Play.init()
})

import * as React from 'react'
import './DeviceBlock.scss'

function DeviceBlock (props) {
  return (
    <div 
      className='device-blocking' 
      style={{ backgroundImage: `url(${props.backgroundImage})` }}
    >
      <div className='container'>
        <div className='logo'>
          <img src={props.logo} />
        </div>
        <div className='message'>
          <h1>Content</h1>
          <a href='/' className='btn btn--primary btn--lg'>Link</a>
        </div>
      </div>
    </div>
  );
}

export default DeviceBlock

请注意,我的解决方案仅适用于您自己服务器上处理过的图片,而不是来自其他URL。

如果图片来自其他URL,则不应导入这些URL并直接将它们添加到props中。

<DeviceBlock
  backgroundImage="url-to-background.png",
  logo="url-to-logo.png"
/>

我已经更新了我的问题,包括完整的代码范围,以便通过将图像从Play组件传递到Blocker组件来实现我的目标。 - Matt
更新了我的回答。 - Kenneth Truong
这帮助我朝着正确的方向前进,尽管我不得不稍微修改答案。 - Matt

5

样式是一个对象。试试这样:

style={{backgroundImage: this.state.backgroundImage}}

此外,在函数式组件中,您不能同时拥有构造函数和使用状态。要么将组件转换为常规的React组件并保留状态,要么将状态部分放在常规的React组件中,并将其作为props传递到函数式组件中。这也在@Kenneth Truong的答案中提到。
要将其转换为常规的React组件,可以执行以下操作:
class DeviceBlock extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      backgroundImage: "url('url-to-background.png')",
      logo: "url('url-to-logo.png')";
    }
  }
  render() {
    return (
      <div className='device-blocking' style={{backgroundImage: this.state.backgroundImage}}>
        <div className='container'>
          <div className='logo'>
            <img src='{{this.state.logo}}' />
          </div>
          <div className='message'>
            <h1>Content</h1>
            <a href='/' className='btn btn--primary btn--lg'>Link</a>
          </div>
        </div>
      </div>
    )
  }
}

你可以在这里看到它的运行效果: https://codepen.io/anon/pen/zWexzO 更新:
根据问题的最新变化,你也可以将其保留为一个函数组件并传递props:
class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      backgroundImage: "url('url-to-background.png')",
      logo: "url('url-to-logo.png')";
    }
  }
  render() {
    return (
      <DeviceBlock 
        backgroundImage={this.state.backgroundImage}
        logo={this.state.logo}/>
    )
  }
}

const DeviceBlock = (props) => {
    return (
      <div className='device-blocking' style={{backgroundImage: props.backgroundImage}}>
        <div className='container'>
          <div className='logo'>
            <img src='{{props.logo}}' />
          </div>
          <div className='message'>
            <h1>Content</h1>
            <a href='/' className='btn btn--primary btn--lg'>Link</a>
          </div>
        </div>
      </div>
    )
} 

https://codepen.io/anon/pen/OvdPOQ

这个应用组件只是演示你可以传递一些动态状态。当然,你可以像在提供的代码中那样直接从Play.init函数中渲染DeviceBlock组件(然后可以忽略应用组件部分)。


你应该将它转换为字符串:url('url-to-background-image.png') => "url('url-to-background-image.png')" - the_cheff
已应用推荐并更新了上面的代码,但图片仍无法加载。 - Matt
实际上,整个语法对我来说有点奇怪。这是一个功能组件,对吧?那么你就无法访问状态。要么将其变成常规的React组件,要么将backgroundimage和logo作为props传递下去。 - the_cheff
这是一个展示性组件,将用于另一个项目,因此需要传入背景图像。 - Matt
我已经更新了问题,包括完整的代码范围,以使我尝试做什么更清晰。我需要能够从父Play传递图像到Blocker组件中。 - Matt
显示剩余3条评论

1

我成功地将图片传递到父组件中的<DeviceBlock />,并在子组件中显示:

<DeviceBlock
    backgroundImage="background-image-url.png"
    logo="logo-image-url.png" />,
    container

然后将它们作为子组件的属性传递

<div className='device-blocking' style={{ backgroundImage: `url(${props.backgroundImage})` }}>
  <div className='container'>
    <div className='logo'>
      <img src={props.logo} />
    </div>
    <div className='message'>
      <h1>Content</h1>
      <a href='/' className='btn btn--primary btn--lg'>Link text</a>
    </div>
  </div>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接