SVG使用标签与ReactJS

138

通常情况下,为了包含大部分需要简单样式的SVG图标,我会这样做:

<svg>
    <use xlink:href="/svg/svg-sprite#my-icon" />
</svg>

最近我一直在尝试使用ReactJS,将其作为我的新前端开发堆栈中的一个可能的组件。然而,我注意到在它支持的标签/属性列表中,既没有use也没有xlink:href

在ReactJS中是否可能使用SVG sprites并以这种方式加载它们?


41
未来的访问者,您现在可以使用 <use xlinkHref="/svg/svg-sprite#my-icon" /> - David Gilbertson
9
xlink:href已经过时,现在应该只使用href -- https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href - Matt Greer
2
截至2018年,Safari仍需要使用xlink:href,因此我们仍然需要使用它。实际的Web应用程序需要使用浏览器功能的共同点,或者实现特定的解决方案/填充。 - Tobia
我只是添加这个评论来帮助那些搜索这个错误的人,这个错误已经被Jon Surrell在下面的回答中解决了:属性“xlink”在类型“SVGImageElement的SVGProps”上不存在 - Joe M
嘿,也许可以接受一个不同的答案?社区似乎对此达成了共识。这只是一个有益的建议,谢谢。 - HoldOffHunger
7个回答

311

MDN说xlink:href已经被弃用,应该使用href属性。你可以直接使用href属性。下面的示例包括两个版本。

React 0.14开始,xlink:href通过React作为xlinkHref属性可用。在0.14版本的发布说明中,它被列为“值得注意的增强功能”之一。

<!-- REACT JSX: -->
<svg>
  <use xlinkHref='/svg/svg-sprite#my-icon' />
</svg>

<!-- RENDERS AS: -->
<svg>
  <use xlink:href="/svg/svg-sprite#my-icon"></use>
</svg>

更新于2018-06-09:添加了有关hrefxlink:href属性的信息,并更新示例以包含两者。 感谢 @devuxer

更新3:在撰写本文时,可以在React主SVG属性中找到此处

更新2:似乎现在所有svg属性都应该可以通过react使用(请参见合并的svg属性PR)。

更新1:您可能想要关注GitHub上的与SVG相关的问题,以获取更多支持SVG的开发进展。

演示:

const svgReactElement = (
  <svg
    viewBox="0 0 1340 667"
    width="100"
    height="100"
  >
    <image width="667" height="667" href="https://i.imgur.com/w7GCRPb.png"/>
    { /* Deprecated xlink:href usage */ }
    <image width="667" height="667" x="673" xlinkHref="https://i.imgur.com/w7GCRPb.png"/>
  </svg>
);

var resultHtml = ReactDOMServer.renderToStaticMarkup(svgReactElement);
document.getElementById('render-result-html').innerHTML = escapeHtml(resultHtml);

ReactDOM.render(svgReactElement, document.getElementById('render-result') );

function escapeHtml(unsafe) { return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom-server.browser.development.js"></script>

<h2>Render result of rendering:</h2>
<pre>&lt;svg
  viewBox=&quot;0 0 1340 667&quot;
  width=&quot;100&quot;
  height=&quot;100&quot;
&gt;
  &lt;image width=&quot;667&quot; height=&quot;667&quot; href=&quot;https://i.imgur.com/w7GCRPb.png&quot;/&gt;
  { /* Deprecated xlink:href usage */ }
  &lt;image width=&quot;667&quot; height=&quot;667&quot; x=&quot;673&quot; xlinkHref=&quot;https://i.imgur.com/w7GCRPb.png&quot;/&gt;
&lt;/svg&gt;</pre>

<h2><code>ReactDOMServer.renderToStaticMarkup()</code> output:</h2>
<pre id="render-result-html"></pre>
<h2><code>ReactDOM.render()</code> output:</h2>
<div id="render-result"></div>


2
更新于2015年12月25日:看起来现在所有的SVG属性都可以通过React使用(请参见合并的SVG属性PR)。 有没有一种标准的方法来使用这些SVG属性?它们是否都像xlink:href => xlinkHref一样采用驼峰式命名? - tnrich
@majorBummer请看这里:(https://github.com/facebook/react/blob/dff05beeff9562647950461830ce42d484ca55fa/src/renderers/dom/shared/SVGDOMPropertyConfig.js#L58-L83) - Jon Surrell
2
这真的需要成为正确的答案,尤其是当前选择的答案建议使用dangerouslySetInnerHTML,这是非常危险的。 - feihcsim
1
根据 MDN (https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href),`xlink:href`已被弃用,建议使用没有命名空间前缀的 href。(但是请注意,如果您正在使用 TypeScript,则尚未更新类型定义以反映这一点。) - devuxer
xlink:href在SVG 2.0中已被弃用,但它仍然是一个正在进行中的工作,并没有完整的浏览器实现,同时旧版浏览器不支持SVG 2。 - Andrey Izman
显示剩余2条评论

52

2018年9月更新: 这种解决方案被弃用了,请阅读Jon的答案代替。

--

正如您所说,React不支持所有SVG标记,这里有一个支持的标记列表。他们正在努力扩大支持范围,例如在此票证中。

一种常见的解决方法是注入HTML替换不支持的标记,例如:

render: function() {
    var useTag = '<use xlink:href="/svg/svg-sprite#my-icon" />';
    return <svg dangerouslySetInnerHTML={{__html: useTag }} />;
}

23
不要使用dangerouslySetInnerHTML,你可以使用下面提到的xlinkHref - Tobia
2
作者可能应该将此答案取消接受。 - Theorder

10

如果你遇到了 xlink:href,那么在 ReactJS 中,你可以通过删除冒号并将添加的文本转为驼峰式来获得等效的内容: xlinkHref

你可能最终会在 SVG 中使用其他名称空间标签,比如 xml:space 等。 同样的规则也适用于它们(即 xml:space 变成了 xmlSpace)。


6

如Jon Surrell的回答中所述,现在已经支持使用use标签。如果您不使用JSX,可以按照以下方式实现:

React.DOM.svg( { className: 'my-svg' },
    React.createElement( 'use', { xlinkHref: '/svg/svg-sprite#my-icon' }, '' )
)

3
我创建了一个小助手来解决这个问题:https://www.npmjs.com/package/react-svg-use 首先安装npm i react-svg-use -S,然后简单使用。
import Icon from 'react-svg-use'

React.createClass({
  render() {
    return (
      <Icon id='car' color='#D71421' />
    )
  }
})

然后会生成以下标记:
<svg>
  <use xlink:href="#car" style="fill:#D71421;"></use>
</svg>

1
伙计,你必须因此获得+500分的表扬! - Igor Shumichenko

0

这是 SVG 组件。

const SvgComponent = () => {
    return <svg width="0" height="0">
        <defs>
            <symbol id="test" viewBox="0 0 100 100">
                <line x1='0' y1='50' x2='100' y2='50' strokeWidth='8' stroke="#000" />
            </symbol>
        </defs>
    </svg>
}

export default SvgComponent

使用组件

import SvgComponent from './SvgComponent';

export default function App() {
  return (
    <>
      <SvgComponent/>
      <svg>
        <use xlinkHref="#test"></use>
      </svg>
    </>
  );
}

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0

我在 Gutenberg 块中显示 SVG 时遇到了问题,通过引用 xlink:href 来解决。我们在 React 中使用了 xlinkHref 属性,但编译后,它被渲染为 xlinkhref 而不是 xlink:href,因此 SVG 没有显示出来。经过多次检查,我发现 xlink:href 已经被弃用了(尽管如果我们在 HTML 中或直接在 Chrome 开发工具中添加它,它仍然有效),应该使用 href 替代。所以将其更改为 href 后,它就可以正常工作了。

"SVG 2 取消了 xlink 命名空间的需要,因此您应该使用 href 而不是 xlink:href。" https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href

这是我使用的代码

SVG 文件

<svg id="svg-source" style="display: none;" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
    <symbol id="svg-arrow-accordion" viewBox="0 0 15 24" fill="none">
        <path id="Path_1662" data-name="Path 1662" d="M15.642,14.142h-3V1.5H0v-3H15.642Z" transform="translate(2 2) rotate(45)" fill="currentColor"></path>
    </symbol>
</svg>

React文件

<svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="15" height="24">
<use href="#svg-arrow-accordion"></use>
</svg>

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