Web paketini kullanarak bir dizinden dinamik olarak görüntüleri içe aktarın


104

İşte ES6 aracılığıyla web paketindeki görüntüleri ve simgeleri içe aktarmak için mevcut iş akışım:

import cat from './images/cat1.jpg'
import cat2 from './images/cat2.svg'
import doggy from './images/doggy.png'
import turtle from './images/turtle.png'

<img src={doggy} />

Bu hızla dağınık hale geliyor. İşte istediğim şey:

import * from './images'

<img src={doggy} />
<img src={turtle} />

Tüm dosyaları belirli bir dizinden dinamik olarak adlarının uzantısı olarak içe aktarmanın ve sonra bu dosyaları gerektiği gibi kullanmanın bir yolu olması gerektiğini düşünüyorum.

Bunun yapıldığını gören ya da en iyi yol hakkında düşüncesi olan var mı?


GÜNCELLEME:

Seçilen cevabı kullanarak şunu yapabildim:

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

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

<img src={images['doggy.png']} />

8
Ben sadece bu .maptür bir dönüş değeri beklediğini belirtmek isterim . Senin durumunda, forEachonun yerine iyi bir ol ' kullanırdı.
Bram Vanroy

1
@BramVanroy veya sadece tek r.keys.().map(...)
hatlı yapın

Yanıtlar:


124

Tüm dosyaları belirli bir dizinden dinamik olarak adlarının uzantısı olarak içe aktarmanın ve sonra bu dosyaları gerektiği gibi kullanmanın bir yolu olması gerektiğini düşünüyorum.

ES6'da değil. Bütün noktası importve exportbu bağımlılıkları tespit edilebilir statik yani kod çalıştırmadan.

Ancak webpack kullandığınız için bir göz atın require.context. Aşağıdakileri yapabilmelisiniz:

function importAll(r) {
  return r.keys().map(r);
}

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

İlginç ... Bu nedenle, tüm bu dosyaları uygulamalarımın genel dizininde tek bir konuma taşımak için şu anda web paketi yapılandırmamda 'dosya yükleyici'yi kullanıyorum. Burada olmuyor. Yükleyiciler require.context ile nasıl çalışır?
klinore

1
"Burada olmuyor" Yani dosyaların çıktı klasöründe görünmediğini mi söylüyorsunuz? Yine de yukarıdaki kodla onlara giden yolu alıyor musunuz? Bunu desteklemek için özel bir şey yapılması gerektiğini düşünmüyorum ...
Felix Kling

2
Neden olduğundan emin değilim, yükleyicim çalışmıyordu ve orijinal yolu alıyordum. Yükleyici şimdi iyi çalışıyor ve doğru yol sağlanıyor! Harika. Require.context: D'ye giriş yaptığınız için teşekkür ederiz!
klinore

1
Create-react-app (cra) varsa ne kullanmalıyım? içinde cra importAllhiçbir şey geri döndü.
giorgim

2
Bu benim için çalışıyor, ancak aynı şeyi TypeScript'te nasıl yazarsınız? Bunun için doğru türler ne olabilir?
Maximilian Lindsey

10

Bu kolay. Sen kullanabilirsiniz requireiçindeki (statik yöntem, ithalat sadece dinamik dosyalar içindir) render. Aşağıdaki örnekte olduğu gibi:

render() {
    const {
      someProp,
    } = this.props

    const graphImage = require('./graph-' + anyVariable + '.png')
    const tableImage = require('./table-' + anyVariable2 + '.png')

    return (
    <img src={graphImage}/>
    )
}

1
Bunun web paketi ile çalışması için daha çok şey yapılması gerektiğini düşünüyorum.
Felix Kling 08

Web paketi yapılandırma dosyanızı buraya yapıştırabilir misiniz?
Robsonsjre

3
Bu muhteşem. Teşekkürler!
poweratom

1
Global gereksinimleri bu şekilde kullanmanızı tavsiye etmem - bkz eslint.org/docs/rules/global-require
markyph

7

Au.png, nl.png vb. Gibi isimlendirilmiş png ülke bayrakları dizinim var. Bu yüzden:

-svg-country-flags
 --png100px
   ---au.png
   ---au.png
 --index.js
 --CountryFlagByCode.js

index.js

const context = require.context('./png100px', true, /.png$/);

const obj = {};
context.keys().forEach((key) => {
  const countryCode = key.split('./').pop() // remove the first 2 characters
    .substring(0, key.length - 6); // remove the file extension
  obj[countryCode] = context(key);
});

export default obj;

Bunun gibi bir dosya okudum:

CountryFlagByCode.js

import React from 'react';
import countryFlags from './index';

const CountryFlagByCode = (countryCode) => {
    return (
        <div>
          <img src={countryFlags[countryCode.toLowerCase()]} alt="country_flag" />
        </div>
      );
    };

export default CountryFlagByCode;

5

Bu sorunu çözmek için işlevsel bir yaklaşım:

const importAll = require =>
  require.keys().reduce((acc, next) => {
    acc[next.replace("./", "")] = require(next);
    return acc;
  }, {});

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

Teşekkür ederim! Mükemmel çalışıyor!
Zakalwe

4

GÜNCELLEME Soruyu tam olarak anlamadım gibi görünüyor. @Felix doğru anladı, bu yüzden cevabını kontrol et. Aşağıdaki kod yalnızca Nodejs ortamında çalışacaktır.

Klasöre bir index.jsdosya ekleyinimages

const testFolder = './';
const fs = require('fs');
const path = require('path')

const allowedExts = [
  '.png' // add any extensions you need
]

const modules = {};

const files = fs.readdirSync(testFolder);

if (files && files.length) {
  files
    .filter(file => allowedExts.indexOf(path.extname(file)) > -1)
    .forEach(file => exports[path.basename(file, path.extname(file))] = require(`./${file}`));
}

module.exports = modules;

Bu, her şeyi başka bir dosyadan içe aktarmanıza izin verecek ve Wepback onu ayrıştırıp gerekli dosyaları yükleyecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.