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

IT技术 javascript reactjs svg dynamic import
2021-05-23 04:24:05

我有一个组件,它接受一个 :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/”

我觉得我只是遗漏了最后一条关键信息,在搜索过去一天之后,我希望有人能找出我遗漏的那条信息。

4个回答

如果使用 React,我强烈怀疑您也在使用 Webpack。您可以使用require.contextes6 代替,Webpackimport会在构建时为您解决。

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

每个示例的第一行...

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

... 创建一个 Require Context 将*.svg文件images夹中的所有文件路径映射到导入。这为我们提供了一个特殊的 Require 函数,并以reqSvgs一些附加属性命名

的属性之一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 给出了require.context此处 SurviveJS Webpack 动态加载的更通用示例

偶然发现了这个问题 - 我最初有“接受的答案”,但我为每个 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 loader 和 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 包含在 bundle 中并且没有单独的 http 请求🎊🎉

您可以使用单个 SVG 精灵代替多个 SVG 文件。

可以使用svg-sprite-generator从 SVG 文件目录生成 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>
)

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