如何将 SVG 图像的整个文件夹(或如何动态加载它们)导入到 React Web App 中?

问题描述 投票:0回答:6

我有一个组件,它接收 :itemName 并输出包含图像的 html 包。每个捆绑包的图像都不同。

这是我所拥有的:

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

import SVGInline from "react-svg-inline";

export default (props) => (
  <NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}> {React.createElement(SVGInline, {svg: props.itemName})} </NavLink>
)

我怎样才能让这个组件工作?

我知道,如果我只是显式导入所有图像,我可以像这样调用我的图像......

import SVGInline from "react-svg-inline";
import SASSSVG from "./images/sass.svg";

<NavLink className="hex" activeClassName="active" to="/hex/sass"><SVGInline svg={ SASSSVG } /></NavLink>

这可行,但由于我需要包含 ~60 个 svgs,所以它添加了很多多余的代码。

另外,我发现在这个问题中这段代码......

import * as IconID from './icons';

但这似乎不起作用(这是问题的一部分,而不是答案),而且答案有点太不具体,无法回答我要问的问题。

我还发现了这个问题,但同样有一个答案(尽管未经批准)所包含的问题多于它的答案。所以,在安装了react-svg之后,我设置了一个测试来看看答案是否像这样工作......

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import { NavLink } from 'react-router-dom';
import ReactSVG from 'react-svg'

export default (props) => (
  <NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}>
    <ReactSVG
      path={"images/" + props.itemName + ".svg"}
      callback={svg => console.log(svg)}
      className="example"
    />
  </NavLink>
)

但是,正如该问题的OP所问的那样,即使将整个图像文件夹复制到构建文件夹中,页面也找不到我的svg。我也尝试过“./images/”

我觉得我只是错过了最后一条关键信息,在搜索了过去的一天之后,我希望有人能够识别我所缺少的信息。

javascript reactjs svg dynamic import
6个回答
29
投票

如果使用 React,我强烈怀疑你也在使用 Webpack。您可以使用

require.context
代替 es6
import
,Webpack 将在构建时为您解决。

require.context ( folder, recurse, pattern )
  • folder - 字符串 - 开始扫描文件的文件夹路径。
  • recurse - 布尔值 - 是否递归扫描文件夹。
  • pattern - RegExp - 描述要包含哪些文件的匹配模式。

每个示例的第一行...

const reqSvgs = require.context ( './images', true, /\.svg$/ )

... 创建一个 Require Context,将

*.svg
文件夹中的所有
images
文件路径映射到导入。这为我们提供了一个名为
reqSvgs
的专门 Require 函数,并带有一些附加属性。

reqSvgs
的属性之一是
keys
方法,它返回所有有效文件路径的列表。

const allSvgFilepaths = reqSvgs.keys ()

我们可以将这些文件路径之一传递到

reqSvgs
来获取导入的图像。

const imagePath = allSvgFilePaths[0]
const image = reqSvgs ( imagePath )

此 api 对于此用例来说是有限制且不直观的,因此我建议将集合转换为更常见的 JavaScript 数据结构,以使其更易于使用。

转换过程中将导入每个图像。小心,因为这可能是一把步枪。但它提供了一种相当简单的机制,用于将多个文件复制到构建文件夹,而其他源代码可能永远不会显式引用该文件夹。

这里有 3 个可能有用的转换示例。


数组

创建导入文件的数组。

const reqSvgs = require.context ( './images', true, /\.svg$/ )
const paths = reqSvgs.keys ()

const svgs = paths.map( path => reqSvgs ( path ) )

对象数组

创建一个对象数组,每个对象对于一张图像来说都是

{ path, file }

const reqSvgs = require.context ( './images', true, /\.svg$/ )

const svgs = reqSvgs
  .keys ()
  .map ( path => ({ path, file: reqSvgs ( path ) }) )

普通物体

创建一个对象,其中每个路径都是其匹配文件的密钥。

const reqSvgs = require.context ('./images', true, /\.svg$/ )

const svgs = reqSvgs
  .keys ()
  .reduce ( ( images, path ) => {
    images[path] = reqSvgs ( path )
    return images
  }, {} )

SurviveJS 在这里

SurviveJS Webpack 动态加载
给出了更通用的示例 require.context


13
投票

偶然发现这个问题 - 我最初有“已接受的答案”,但我对每个 svg 发出了 http 请求,这触发了速率限制。所以我最终得到了接受的答案和 @karthik 提议的组合 - 在 request.context 中使用加载器

从 CRA 2.0 开始,包含 @svgr 以将 svg 作为 React 组件导入。

const reqSvgs = require.context('!@svgr/webpack!flag-icon-css/flags/4x3', true, /\.svg$/)

所以这里我们结合了 svg 加载器和 require.context

const flagMap = reqSvgs.keys().reduce((images, path) => {
  const key = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.'))
  images[key] = reqSvgs(path).default
  return images
}, {})

然后我们将所有这些映射到一个 json 对象中,以便我们可以使用键查找

在 jsx 中渲染 svg:

const Flag = flagMap['dk']
return (
  <Flag />
)

快乐的日子,svgs 包含在捆绑中,并且没有单独的 http 请求🎊🎉


5
投票

您可以使用单个 SVG 精灵,而不是多个 SVG 文件。

SVG sprite 可以使用 svg-sprite-generator:

从 SVG 文件目录生成
svg-sprite-generate -d images -o images/sprite.svg

然后像这样使用它:

import React from 'react';
import { NavLink } from 'react-router-dom';
import sprite from './images/sprite.svg';

export default (props) => (
  <NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}>
    <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30">
      <use xlinkHref={`${sprite}#${props.itemName}`} />
    </svg>
  </NavLink>
)

1
投票

最好的方法是使用节点模块,例如 [SVG to React Loader] (https://github.com/jhamlet/svg-react-loader)


0
投票

对于 Vite(Vue,但应该适用于其他库)只需使用

const iconsModule = import.meta.glob('@/path/*.svg');

然后您可以迭代路径并获取带或不带格式名称的文件名

for (const path in iconsModule) {
            const icon = path.split('/').slice(-1)[0];
            this.icons.push(icon);
        }

-1
投票

您可以简单地创建一个函数,该函数接受参数“名称”(您的 svg 图标名称)并返回您的 svg 代码。


import React from 'react'
export function getIcon(name){
   switch(name) {
     case 'back':
       return (
          // your svg code here
          <svg></svg>
       )
   }
}

然后您可以将其导入到任何地方,只需用您想要的图标名称来调用它即可。

import { getIcon } from './utils'
render() {
  return (
    <div>
     <span>{ getIcon('back') }</span>
    </div>
  )
}
© www.soinside.com 2019 - 2024. All rights reserved.