简体   繁体   English

如何在 React 中导入 SVG 图标

[英]How to Import SVG icons in React

I wanted to import too many SVG icons in app & each icons required custom color through css, which is the easiest way to import to react?我想在应用程序中导入太多 SVG 图标,并且每个图标都需要通过 css 自定义颜色,这是最简单的导入方式? Importing to <img/> tag won't support the color change via css fill.导入到<img/>标签将不支持通过 css 填充更改颜色。 Creating a.js component for each icon is too hard for 250+ icons.为每个图标创建一个 .js 组件对于 250 多个图标来说太难了。 what is the other option?另一个选择是什么? Please help请帮忙

import IconArrow from "./Arrow.svg";
import Circlearrowdownright from "./Arrow.js";

<img className="ico" src={IconArrow} />
<i className="ico"><Circlearrowdownright /></i>

https://codesandbox.io/s/svg-icon-3z0qu6 https://codesandbox.io/s/svg-icon-3z0qu6

You can import and use it as React component directly:您可以直接将其导入并用作 React 组件:

import { ReactComponent as ExampleIcon} from './icons/ExampleIcon.svg';

<ExampleIcon className="css-class"/>

You can dynamically import SVG & render on the fly ( CodeSandbox ).您可以动态导入 SVG 并即时渲染 ( CodeSandbox )。 No need to create a separate .js component for every SVG file.无需为每个 SVG 文件创建单独的.js组件。

The hook hook

function useDynamicSVGImport(name, options = {}) {
  const ImportedIconRef = useRef();
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState();

  const { onCompleted, onError } = options;
  useEffect(() => {
    setLoading(true);
    const importIcon = async () => {
      try {
        ImportedIconRef.current = (
          await import(`./${name}.svg`)
        ).ReactComponent;
        if (onCompleted) {
          onCompleted(name, ImportedIconRef.current);
        }
      } catch (err) {
        if (onError) {
          onError(err);
        }
        setError(err);
      } finally {
        setLoading(false);
      }
    };
    importIcon();
  }, [name, onCompleted, onError]);

  return { error, loading, SvgIcon: ImportedIconRef.current };
}

Icon component that uses the hook使用钩子的Icon组件

/**
 * Simple wrapper for dynamic SVG import hook. You can implement your own wrapper,
 * or even use the hook directly in your components.
 */
export const Icon = ({ name, onCompleted, onError, ...rest }) => {
  const { error, loading, SvgIcon } = useDynamicSVGImport(name, {
    onCompleted,
    onError
  });
  if (error) {
    return error.message;
  }
  if (loading) {
    return "Loading...";
  }
  if (SvgIcon) {
    return <SvgIcon {...rest} />;
  }
  return null;
};

Usage用法

return (
    <>
      <Icon
        name="Arrow"
        fill="gray"
        width="100"
        onCompleted={handleOnCompleted}
        onError={handleIconError}
      />
      <Icon
        name="delete"
        fill="gray"
        width="50"
        onCompleted={handleOnCompleted}
        onError={handleIconError}
      />
    </>
  );

React works fine with native Web Components. React 与原生 Web 组件配合良好。 Only when you want to interact with them using Events or pass Data is where React (still) fails to support the standard: https://custom-elements-everywhere.com/只有当您想使用事件与它们交互或传递数据时,React(仍然)无法支持标准: https://custom-elements-everywhere.com/

  • Creating a <svg-icon> tag is only a few lines of code.创建一个<svg-icon>标签只需要几行代码。
  • Added a replaceWith attribute so the <svg> you load replaces the <svg-icon> , makes it easier to work with global CSS.添加了一个replaceWith属性,以便您加载的<svg>替换<svg-icon> ,使使用全局 CSS 更容易。
  • Added a shadowRoot attribute to move any content TO shadowDOM添加了shadowRoot属性以任何内容移动到 shadowDOM

 customElements.define("svg-icon", class extends HTMLElement { async connectedCallback( src = this.getAttribute("src"), shadowRoot = this.shadowRoot || this.attachShadow({mode:"open"}) ) { shadowRoot.innerHTML = await (await fetch(src)).text() shadowRoot.append(...this.querySelectorAll("[shadowRoot]")) this.hasAttribute("replaceWith") && this.replaceWith(...shadowRoot.childNodes) } });
 body { display: grid; grid: 1fr/1fr 5fr; } path { stroke: green; stroke-width: .2; fill: red; }
 <svg-icon replaceWith src="https://svg-cdn.github.io/bi-arrows.svg"></svg-icon> <svg-icon src="https://svg-cdn.github.io/simple-worldmap.svg"> <style shadowRoot> path { fill: orange } </style> </svg-icon>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM