动态添加图像React Webpack


76

我一直在尝试找出如何通过React和Webpack动态添加图像。我在src / images下有一个图像文件夹, 在src / components / index下有一个组件。我正在将url-loader与以下配置用于webpack

    {
      test: /\.(png|jpg|)$/,
      loader: 'url-loader?limit=200000'
    }

在组件内,我知道可以在创建组件之前在文件顶部为特定图像添加require(image_path),但我想使该组件通用,并使其具有一个属性,该属性具有从中传递的图像的路径父组件。

我试过的是:

<img src={require(this.props.img)} />

对于实际属性,我尝试了几乎所有可以想到的从项目根目录,反应应用程序根目录以及组件本身到图像的路径。

文件系统

|-- src
|   ` app.js
|   `--images
|      ` image.jpg
|      ` image.jpg
|   `-- components
|      `parent_component.js
|      `child_component.js

父组件基本上只是一个容器,用于容纳子组件的倍数。

<ChildComponent img=data.img1 />
<ChildComponent img=data.img2 />
etc....

有什么方法可以使用带有URL-loader的react和webpack来执行此操作,还是我走了一条错误的道路来实现这一目标?

Answers:


97

使用此处描述的url-loader(SurviveJS-加载图像),然后可以在代码中使用:

import LogoImg from 'YOUR_PATH/logo.png';

<img src={LogoImg}/>

编辑:精确度高,此技术将图像内联到js档案中。对于较小的图像可能值得,但是请明智地使用该技术。


1
我想知道如何从中加载该图像以及返回该图像的API。
甲骨文公司

3
我不确定:如果您希望用户浏览器从API加载图像,则与webpack无关。只需使用变量(可能在调用API之后定义)作为<img> src。这里的想法是将图像包括在您的源和Webpack存档中。(见stackoverflow.com/questions/32612912/...
mlorber

1
谢谢,这很好。您引用的文章最后还提到了如果您使用的是React,那么您可以使用babel-plugin-transform-react-jsx-img-import自动生成导入。这样,您可以编写<img src =“ YOUR_PATH / logo.png” />
Homam Bahrani

警告:url-loader将内嵌图像文件作为base64 ascii字符串。这减少了加载页面所需的文件访问次数,但以下载更多字节为代价。因此,使用文件加载器进行生产可能会更好。
hrabinowitz '19

是的,此技术可以内嵌图像。这完全取决于文件的重量。对于小型(主要是我的图标),这可能是值得的。我将编辑回复
mlorber

22

如果要在服务器端捆绑代码,那么没有什么可以阻止您直接从jsx要求资产:

<div>
  <h1>Image</h1>
  <img src={require('./assets/image.png')} />
</div>

3
这是我在构建组件之前不知道映像文件的情况下需要使用的。我传入一个imageFilename道具,然后使用<img src={require(`./images/${imageFilename}`)} />。感谢您的发布。
布伦丹·摩尔

1
@BrendanMoore,但请记住,在您的情况下,捆绑器(例如webpack)会将images文件夹中的所有图像添加到最终捆绑器中。
James Akwuh

1
正是我想要的。谢谢@JamesAkwuh
Samrat Saha

1
如果这不起作用,则在require()之后添加.default。例如:我使用的是const src = require(资产/图片/ $ {name}).default;
master_dodo,

12

更新:这仅在服务器端渲染(通用Javascript)下进行过测试,这是我的样板

仅使用文件加载器,您就可以动态加载图像-诀窍是使用ES6模板字符串,以便Webpack可以拾取它:

这将工作。:

const myImg = './cute.jpg'
<img src={require(myImg)} />

要解决此问题,只需使用模板字符串即可:

const myImg = './cute.jpg'
<img src={require(`${myImg}`)} />

webpack.config.js:

var HtmlWebpackPlugin =  require('html-webpack-plugin')
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')

module.exports = {
  entry : './src/app.js',
  output : {
    path : './dist',
    filename : 'app.bundle.js'
  },
  plugins : [
  new ExtractTextWebpackPlugin('app.bundle.css')],
  module : {
    rules : [{
      test : /\.css$/,
      use : ExtractTextWebpackPlugin.extract({
        fallback : 'style-loader',
        use: 'css-loader'
      })
    },{
      test: /\.js$/,
      exclude: /(node_modules)/,
      loader: 'babel-loader',
      query: {
        presets: ['react','es2015']
      }
    },{
      test : /\.jpg$/,
      exclude: /(node_modules)/,
      loader : 'file-loader'
    }]
  }
}

2
对我而言,缺少的是webpack配置中的测试。谢谢。
Dean Poulin '18

8

如果您正在寻找一种从图像中导入所有图像的方法

// Import all images in image folder
function importAll(r) {
    let images = {};
    r.keys().map((item, index) => { images[item.replace('./', '')] = r(item); });
    return images;
}

const images = importAll(require.context('../images', false, /\.(gif|jpe?g|svg)$/));

然后:

<img src={images['image-01.jpg']}/>

您可以在此处找到原始线程:使用webpack从目录动态导入图像


6

因此,您必须在父组件上添加导入语句:

class ParentClass extends Component {
  render() {
    const img = require('../images/img.png');
    return (
      <div>
        <ChildClass
          img={img}
        />
      </div>
    );
  }
}

在子类中:

class ChildClass extends Component {
  render() {
    return (
      <div>
          <img
            src={this.props.img}
          />
      </div>
    );
  }
}

3

您没有将图像嵌入捆绑软件中。通过浏览器调用它们。所以这是;

var imgSrc = './image/image1.jpg';

return <img src={imgSrc} />

3
但是,如果您在构建时不了解该图像怎么办?如果图像URL是在运行时组成的,该怎么办?
JBCP

您正在使用的加载程序的目标实际上是在代码中不使用url,并且如果图像足够小(更好的性能),则有可能将图像嵌入存档中
mlorber

2

这是代码

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './image.css';
    import Dropdown from 'react-dropdown';
    import axios from 'axios';

    let obj = {};

    class App extends Component {
      constructor(){
        super();
        this.state = {
          selectedFiles: []
        }
        this.fileUploadHandler = this.fileUploadHandler.bind(this);
      }

      fileUploadHandler(file){
        let selectedFiles_ = this.state.selectedFiles;
        selectedFiles_.push(file);
        this.setState({selectedFiles: selectedFiles_});
      }

      render() {
        let Images = this.state.selectedFiles.map(image => {
          <div className = "image_parent">

              <img src={require(image.src)}
              />
          </div>
        });

        return (
            <div className="image-upload images_main">

            <input type="file" onClick={this.fileUploadHandler}/>
            {Images}

            </div>
        );
      }
    }

    export default App;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.