将SVG嵌入ReactJS

157

是否可能将 SVG 标记嵌入到 ReactJS 组件中?

render: function() {
  return (
    <span>
      <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmln ...
    </span>
  );
}

导致错误的原因:

不支持命名空间属性。ReactJSX 不是 XML。

做这件事情最轻量级的方式是什么?使用像 React ART 这样的东西对我所尝试做的事情来说太过繁琐了。


1
你能创建一个jsbin吗?这可能只需要将你的开头SVG标签更改为<svg id="Layer_1">(或者更好的是,不带id)。编辑:这里有一个例子:http://jsbin.com/nifemuwi/2/edit?js,output - Brigand
@FakeRainBrigand 谢谢!在这种情况下确实很简单。不过看看Ben的回答也是不错的,知道当需要绕过JSX解析时该怎么做。 - nicholas
7个回答

217

更新 2016-05-27

从React v15开始,对于SVG的支持与当前浏览器对SVG的支持(接近?)百分之百相同 (来源)。您只需应用一些语法转换使其与JSX兼容 就像您已经为HTML所做的一样 (classclassName, style="color: purple"style={{color:'purple'}})。对于任何有命名空间(冒号分隔)的属性,例如xlink:href,删除:并将属性的第二部分大写,例如xlinkHref。这是一个具有<defs><use>和内联样式的SVG示例:

function SvgWithXlink (props) {
    return (
        <svg
            width="100%"
            height="100%"
            xmlns="http://www.w3.org/2000/svg"
            xmlnsXlink="http://www.w3.org/1999/xlink"
        >
            <style>
                { `.classA { fill:${props.fill} }` }
            </style>
            <defs>
                <g id="Port">
                    <circle style={{fill:'inherit'}} r="10"/>
                </g>
            </defs>

            <text y="15">black</text>
            <use x="70" y="10" xlinkHref="#Port" />
            <text y="35">{ props.fill }</text>
            <use x="70" y="30" xlinkHref="#Port" className="classA"/>
            <text y="55">blue</text>
            <use x="0" y="50" xlinkHref="#Port" style={{fill:'blue'}}/>
        </svg>
    );
}

工作中的Codepen演示

有关特定支持的更多详细信息,请查看文档中列出的所有支持的SVG属性列表。这是已经关闭了的GitHub问题,用于跟踪命名空间SVG属性的支持。


以前的答案

您可以通过删除命名空间属性来进行简单的SVG嵌入,而无需使用dangerouslySetInnerHTML。例如,这样可以工作:

        render: function() {
            return (
                <svg viewBox="0 0 120 120">
                    <circle cx="60" cy="60" r="50"/>
                </svg>
            );
        }

此时,您可以考虑添加像fill这样的props,或者其他有用的配置。


@ChinonsoChukwuogor 很好的问题! 我不知道,因为我从来没有使用过React Native。 你试过了吗? - Andrew Patton
@AndrewPatton 在带有单引号的多个 CSS 类名中使用反引号无法正常工作:'.class1, .class2{fill: #005baa;}' 如何解决这个问题? - HelloWorld
@HelloWorld 能否给我一个它不起作用的例子?我刚刚将我的原始演示拆分以添加 classB,并且它运行良好:https://codepen.io/acusti/pen/BVJzNg - Andrew Patton
谢谢,从这里开始,我已经成功地将一个svg文件作为React组件导入,而不需要任何加载器,我只是从svg标签中删除了 xmlns:osb="http://www.openswatchbook.org/uri/2009/osb",只留下xlmns。显然这一切都与标签解析有关。以防万一,我也遵循了这些步骤:https://blog.logrocket.com/how-to-use-svgs-in-react/ - funder7
1
为什么人们容忍JSX? - jordanfb

62
如果您只有一个静态的SVG字符串想要包含,您可以使用dangerouslySetInnerHTML:
render: function() {
    return <span dangerouslySetInnerHTML={{__html: "<svg>...</svg>"}} />;
}

React将直接包含标记,而不进行任何处理。


3
我正在使用React控制SVG内部的一些路径,但React似乎不支持滤镜元素。有没有办法支持这个呢?似乎dangerouslySetInnerHTML不起作用,因为我不能在SVG中放置一个span,并且不能用它来设置路径上的滤镜属性。我不认为有一种方式可以像通常创建React元素一样,但让它们将所有属性逐字透传到DOM元素吗? - Andy
截至2019年,似乎可以使用dangerouslySetInnerHTML,但我仍然无法在Chrome上使用dangerouslySetInnerHTML使阴影滤镜正常工作,但在Firefox上可以正常工作。 - Shnd

34

据React开发人员所说, 您不需要使用命名空间xmlns。如果您需要属性xlink:href,则可以从React 0.14开始使用xlinkHref。

示例

Icon = (props) => {
  return <svg className="icon">
    <use xlinkHref={ '#' + props.name }></use>
  </svg>;
}

16

如果你想从文件中加载它,可以尝试使用React-inlinesvg - 这非常简单和直接。

import SVG from 'react-inlinesvg';

<SVG
  src="/path/to/myfile.svg"
  preloader={<Loader />}
  onLoad={(src) => {
    myOnLoadHandler(src);
  }}
>
  Here's some optional content for browsers that don't support XHR or inline
  SVGs. You can use other React components here too. Here, I'll show you.
  <img src="/path/to/myfile.png" />
</SVG>

7

您可以导入SVG,并像图片一样使用它。

import chatSVG from '../assets/images/undraw_typing_jie3.svg'

并将其用在img标签中

<img src={chatSVG} className='iconChat' alt="Icon chat"/>

1
问题要求特别嵌入SVG内联。 - Phani Rithvij
3
那么如果你需要改变颜色呢? - Muhammed Moussa
我相信这不是最初要求的。 - leopinzon

4

我发现最好的方法是使用这个网站:

https://react-svgr.com/playground/

你只需要复制一个svg图像,它就会为你生成一个React函数组件,其中包含将svg转换为React代码的转换。


2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接