[英]How to Import SVG icons in React
我想在應用程序中導入太多 SVG 圖標,並且每個圖標都需要通過 css 自定義顏色,這是最簡單的導入方式? 導入到<img/>
標簽將不支持通過 css 填充更改顏色。 為每個圖標創建一個 .js 組件對於 250 多個圖標來說太難了。 另一個選擇是什么? 請幫忙
import IconArrow from "./Arrow.svg";
import Circlearrowdownright from "./Arrow.js";
<img className="ico" src={IconArrow} />
<i className="ico"><Circlearrowdownright /></i>
您可以直接將其導入並用作 React 組件:
import { ReactComponent as ExampleIcon} from './icons/ExampleIcon.svg';
<ExampleIcon className="css-class"/>
您可以動態導入 SVG 並即時渲染 ( CodeSandbox )。 無需為每個 SVG 文件創建單獨的.js
組件。
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
組件
/**
* 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;
};
用法
return (
<>
<Icon
name="Arrow"
fill="gray"
width="100"
onCompleted={handleOnCompleted}
onError={handleIconError}
/>
<Icon
name="delete"
fill="gray"
width="50"
onCompleted={handleOnCompleted}
onError={handleIconError}
/>
</>
);
React 與原生 Web 組件配合良好。 只有當您想使用事件與它們交互或傳遞數據時,React(仍然)無法支持標准: https://custom-elements-everywhere.com/
<svg-icon>
標簽只需要幾行代碼。replaceWith
屬性,以便您加載的<svg>
替換<svg-icon>
,使使用全局 CSS 更容易。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.