我有一个组件,它接受: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,它会增加很多多余的代码。
另外,我发现in this question这段代码......
import * as IconID from './icons';
但这似乎不起作用(这是问题的一部分,而不是答案),答案对于回答我提出的问题来说有点过于特殊。
我还发现了this question但是又有一个答案(虽然未经批准),其答案多于答案。因此,在安装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 /”
我觉得我只是错过了最后一条关键信息,在寻找过去一天之后,我希望有人可以找到我失踪的那条。
答案 0 :(得分:11)
如果使用React,我强烈怀疑你也在使用Webpack。您可以使用require.context
代替es6 import
,Webpack会在构建时为您解析。
require.context ( folder, recurse, pattern )
- folder - String - 开始扫描文件的文件夹的路径。
- recurse - Boolean - 是否递归扫描文件夹。
- pattern - RegExp - 描述要包含哪些文件的匹配模式。
每个例子的第一行......
const reqSvgs = require.context ( './images', true, /\.svg$/ )
...创建Require Context将*.svg
文件夹中的所有images
文件路径映射到导入。这为我们提供了一个名为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: svg ( path ) } )
创建一个对象,其中每个路径都是其匹配文件的键。
const reqSvgs = require.context ('./images', true, /\.svg$/ )
const svgs = reqSvgs
.keys ()
.reduce ( ( images, path ) => {
images[path] = reqSvgs ( path )
return images
}, {} )
SurviveJS在require.context
setupUi()
提供了更为通用的示例。
答案 1 :(得分:2)
您可以使用单个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>
)
答案 2 :(得分:1)
最好的方法是使用像[SVG to React Loader]这样的节点模块(https://github.com/jhamlet/svg-react-loader)
答案 3 :(得分:1)
偶然发现此问题-我最初有“已接受的答案”,但我对每个svg都发出了http请求,这触发了速率限制。因此,我最终获得了可接受的答案和@karthik提出的建议的组合-在request.context中使用加载器
从CRA 2.0开始,@ svgr已包含在内,用于将svg作为反应组件导入。
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 />
)
开心的日子,捆绑包中包含svg,没有单独的http请求??
答案 4 :(得分:0)
你可以简单地创建一个带有参数“name”(你的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>
)
}