使用React创建SVG图标系统

发布于 大漠

Icon图标在Web应用或Web页面中起着至关重要的作用。它除了起到一定装饰作用之外,还可以在不添加任何文本信息的情况之下向用户传达正确的含义。在当今的Web开发中,有许多不同的方式将图标运用于Web应用或Web页面上。同样,在社区中也有很多介绍Icon图标系统构建的方法,比如早期的雪碧图字体图标以及SVG Sprites等。但是今天我想从不同的角度来和大家聊聊,如何基于React框架下构建属于自己的SVG图标系统。感兴趣的同学,欢迎继续往下阅读。

特别声明:如果你是基于Vue框架开发,你可以移步阅读《如何在Vue项目中使用SVG Icon》一文,当然,文章中提到的相关技术同样也适应于Vue体系以及其他的开发体系。

为什么选择使用SVG Icons

早在几年前,我在《Web中的图标》一文中就和大家一起探讨过图标在Web开发中的几种使用方式以及他们之间的利弊。其实随着CSS的@font-face特性的到来,使用字体图标比使用雪碧图更受欢迎。但最近几年,随着客户端对SVG的支持越来越友好,不管是设计师还是开发者越来越觉得SVG图标要比字体图标还要更友好。在社区中有关于这方面的讨论也比较多,比如 @Chris Coyier的《Inline SVG vs Icon Fonts》@Mallik Cheripally的《Inline SVG or Icon Fonts: Which One to Use》文章就做过详细的对比。

就算是到今天为止,这样的话题也没有停止过。不过我自己觉得,使用SVG Icon有以下几点优势:

  • 可读性:SVG可以直接内联使用,开发者可以在SVG代码中直接添加title以及ARIA相关的特性,这极大地提高了可访问性(A11Y),特别是在仅用图标向用户传递信息的情况下。相比之下,字体图标在这方面就处于劣势(当然可以借画其他手段来实现A11Y的能力)
  • 清晰度:众所周知,SVG是矢量图,它不会因为不同的分辨率造成不清晰;而字体图标在一些显示器上不那么清晰。虽然使用CSS的font-smoothing让字体图标避免这种情况,但是“不完全将字体平滑化”,font-smoothing属性是很难覆盖到
  • 加载失败:可能很多同学都越到过,使用字体图标的时候,Web页面渲染的时候,字体图标会以一个带有x符号的方框替代的情况,这主要是因为跨域(CORS)问题或Opera mini造成字体文件加载失败引起的,这也是使用字体图标很蛋疼的地方。而在SVG中是不会出现这个现象
  • 扩展性:对于字体图标,如果希望给图标某部分改变样式或加载动效,那么是不可能实现的;但SVG图标可以轻易做到。这主要是因为SVG是XML标记语言,可以像操作DOM一样操作SVG的元素,这样一来,就可以晚于给SVG图标的某部分改变样式(比如填充颜色),甚至添加动效

当然,SVG还有其他的优势。这也是SVG Icon被运用于Web开发中的主要原因之一。另外,如果你在Web开发当中,经常会用到图标的话,那么我们构建一个图标系统就变得尤其重要;还有一点,如果你以前就有一个字体图标系统,希望将它们换成SVG图标系统,那么接下来的内容就对你非常有用。

SVG使用姿势

SVG(或者说SVG图标)运用于Web有很多种方式,不过众多方式中更推荐于内联方式,特别是SVG图标的使用场景。

在当下Web开发一般都是基于一些JavaScript框架进行开发,比如说React,Vue等。这些前端开发框架允许我们将UI抽出来,构建成一个可复用的UI组件。这也意味着,我们可以创建一个通用的图标组件,并使用type属性来指定SVG图标,然后以内联方式呈现在Web页面中。比如:

<Icon type="book"  />

如何是在React框架下还可以直接将SVG文件当React组件使用:

import { ReactComponent as ReactLogo } from './logo.svg';
<ReactLogo className="App-logo" />

当然,具体的使用有很多种方式,正如《SVG在React中的运用》和《如何在Vue项目中使用SVG Icon》中所介绍的,我们可以直接将.svg文件转换成Web组件使用。

特另声明,只要你是基于类似于Webpack来构建的项目,有很多方式将SVG转换成Web组件(不同的加载器,使用方式略有细微的差异)

接下来,我们以几种不同的方式来看看怎么一步一步构建属于自己的SVG图标系统。注意,下面的内容都是基于React体进行开发的。

SVG Sprites

在《SVG在React中的运用》中我们介绍的几种将SVG自动转换为React组件的使用方式,虽然方式不同,但最终呈现在Web中的效果是一样的。文章中提到的几种方式都有着一个共性:

SVG内联到HTML

他们有着一个最大的优势:直接将SVG文件转换为React组件,但也有着一个最明显的缺点,比如说,我在同一个页面不同的地方使用了同一个SVG图标组件,这个时候会有相同的代码插入到DOM中:

import {ReactComponent as Home} from 'home.svg'

const App = () => (
    <>
        <header>
            <Home />
        </header>
        <!-- ... -->
        <footer>
            <Home />
        </footer>
    </>
)

export default App

这个时候,渲染出来的Web页面,你会发现在<header><footer>引入了两段相同的SVG代码,类似像下面这样:

<div id="root">
    <header>
    <svg t="1598444628462" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1160" width="200" height="200">
        <path d="M950.153231 461.510311l-122.16073-111.794026-1.27984-1.087864 0-136.87889c0-10.110736-8.190976-18.365704-18.365704-18.365704l-82.549681 0c-10.110736 0-18.365704 8.190976-18.365704 18.365704l0 35.835521-5.11936-4.351456-150.829146-134.255218c-0.63992-0.575928-1.343832-1.023872-1.983752-1.471816-11.070616-8.766904-24.060992-13.43832-37.563305-13.43832-14.07824 0-27.51656 4.991376-38.971129 14.526184-0.127984 0.191976-0.31996 0.383952-0.511936 0.447944l-398.670166 352.595926c-10.55868 9.086864-12.926384 26.428696-5.247344 38.907137 7.67904 12.414448 22.525184 15.230096 33.083865 6.207224l398.350206-352.40395c0.063992 0 0.191976-0.127984 0.255968-0.191976C503.68104 151.149106 507.712536 149.613298 512 149.613298s8.31896 1.535808 11.710536 4.415448c0.191976 0.127984 0.383952 0.255968 0.575928 0.383952l398.094238 352.211974c10.55868 9.022872 25.404824 6.271216 33.083865-6.207224C963.079615 487.939008 960.775903 470.597175 950.153231 461.510311z" p-id="1161" />
        <path d="M543.868016 271.1981c0-0.063992-0.127984-0.127984-0.191976-0.191976-9.342832-7.807024-20.349456-11.966504-31.740032-12.030496-11.390576 0-22.333208 4.15948-31.67604 11.902512-0.063992 0.127984-0.191976 0.191976-0.31996 0.31996l-276.189476 247.969004c-6.207224 5.311336-9.790776 13.694288-9.790776 22.525184l0.191976 328.598925c0 32.955881 26.748656 59.704537 59.704537 59.704537l156.780402 0 0-204.198475c0-41.338833 28.412448-74.742657 63.480065-74.742657l65.911761 0c35.067617 0 63.544057 33.403825 63.544057 74.742657l0 204.198475 166.315211 0c32.955881 0 59.704537-26.748656 59.704537-59.704537l0.255968-328.598925c0-8.830896-3.647544-17.213848-9.790776-22.525184L543.868016 271.1981z" p-id="1162" />
        </svg>
    </header>
    <!-- ... -->
    <footer>
        <svg t="1598444628462" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1160" width="200" height="200">
            <path d="M950.153231 461.510311l-122.16073-111.794026-1.27984-1.087864 0-136.87889c0-10.110736-8.190976-18.365704-18.365704-18.365704l-82.549681 0c-10.110736 0-18.365704 8.190976-18.365704 18.365704l0 35.835521-5.11936-4.351456-150.829146-134.255218c-0.63992-0.575928-1.343832-1.023872-1.983752-1.471816-11.070616-8.766904-24.060992-13.43832-37.563305-13.43832-14.07824 0-27.51656 4.991376-38.971129 14.526184-0.127984 0.191976-0.31996 0.383952-0.511936 0.447944l-398.670166 352.595926c-10.55868 9.086864-12.926384 26.428696-5.247344 38.907137 7.67904 12.414448 22.525184 15.230096 33.083865 6.207224l398.350206-352.40395c0.063992 0 0.191976-0.127984 0.255968-0.191976C503.68104 151.149106 507.712536 149.613298 512 149.613298s8.31896 1.535808 11.710536 4.415448c0.191976 0.127984 0.383952 0.255968 0.575928 0.383952l398.094238 352.211974c10.55868 9.022872 25.404824 6.271216 33.083865-6.207224C963.079615 487.939008 960.775903 470.597175 950.153231 461.510311z" p-id="1161" />
            <path d="M543.868016 271.1981c0-0.063992-0.127984-0.127984-0.191976-0.191976-9.342832-7.807024-20.349456-11.966504-31.740032-12.030496-11.390576 0-22.333208 4.15948-31.67604 11.902512-0.063992 0.127984-0.191976 0.191976-0.31996 0.31996l-276.189476 247.969004c-6.207224 5.311336-9.790776 13.694288-9.790776 22.525184l0.191976 328.598925c0 32.955881 26.748656 59.704537 59.704537 59.704537l156.780402 0 0-204.198475c0-41.338833 28.412448-74.742657 63.480065-74.742657l65.911761 0c35.067617 0 63.544057 33.403825 63.544057 74.742657l0 204.198475 166.315211 0c32.955881 0 59.704537-26.748656 59.704537-59.704537l0.255968-328.598925c0-8.830896-3.647544-17.213848-9.790776-22.525184L543.868016 271.1981z" p-id="1162" />
        </svg>
    </footer>
</div>

这对于有代码洁癖的同学来说,可能无法接受。

如果你对SVG的基础有点了解话,你可能会想到SVG的<symbol><use>元素。比如下面这个简单示例:

<svg style="display:none;">
    <!-- Twitter Icon -->
    <symbol id="twitter" viewBox="0 0 32 32">
        <path d="M32 6.076c-1.177 …" fill="#000000"></path>
    </symbol>

    <!-- Facebook Icon -->
    <symbol id="facebook" viewBox="0 0 32 32">
        <path d="M32 6.076c-1.177 …" fill="#000000"></path>
    </symbol>

    <!-- 其他Icon图标 -->
</svg>

然后在需要使用图标的地方用<use>标签来引用对应<symbole>中的id名:

<svg class="twitter__icon">
    <use xlink:href="#twitter"></use>
<svg>

我复制了@Adam Moore在CodePen的示例,向大家展示SVG的<symbole><use>的具体使用和对应效果:

如果你使用浏览器查看代码的话,会像下图这样:

而这种方法也被称为是SVG Sprites。社区中有关于这方面的讨论也非常的多:

其实在《如何在Vue项目中使用SVG Icon》一文中也介绍了这种方法来构建SVG Sprites,不过这里想和大家接着聊在React中如何基于Webpack的加载器(比如svg-sprite-loader)构建SVG Sprites图标系统。

特别声明:下面的示例是基于Create React App构建的React项目,并且通过npm run eject命令开启了Webpack的自定义配置

规划项目目录和准备SVG图标

首先需要有一个地方(文件目录)来放置SVG图标。所以我在src/目录下创建了一个新目录assets/,并且在assets目录下创建了icons/目录,主要用来放置SVG图标。为了节约时间,我直接在iconfont.cn平台上下载了一些SVG图标:

生成SVG Sprite:svg-sprite-loader

前面向大家演示了,在SVG中如何使用<defs><symbol>标签来构建SVG Sprites的表(每个<symbol>对应的是一个SVG图标)。但是在React框架开发体系下,我们可以借助Webpack的工程配置能力和 svg-sprite-loader可以根据自动引入的SVG图标生成对应的SVG Sprites表。

假设你已具备了一个React的开发体系(基于Webpack),那么可以在项目中安装svg-sprite-loader

» npm i --save-dev svg-sprite-loader

并且在webpack.config.js中添加有关于svg-sprite-loader相关的配置:

module: {
    rules: [
        {
             oneOf: [
                 {
                    test: /\.svg$/,
                    loader:  require.resolve('svg-sprite-loader'), 
                    options: { 
                        symbolId: 'icon-[name]'
                    } 
                },
             ]
        }
    ]
}

在此基础上,我们需要一个模板文件。比如在src/assets/icons目目中创建一个index.js文件:

const requireAll = requireContext => requireContext.keys().map(requireContext);

const req = require['context']('./', false, /\.svg$/);

requireAll(req);

可以在项目的index.tsx中引入这个模板文件:

// index.tsx
import './assets/icons/index.js'    

引入了index.js文件之后,那么/src/components/icons目录下的所有.svg文件就会合并成一个SVG Sprites,并且插入到index.html中:

当然,仅有这个还不行,我们还需要一个React组件。比如在/src/components/创建一个SvgIcon组件:

import React from 'react'

interface ISvgIconProps {
    type: string;
    className?: string;
}

const SvgIcon = (props: ISvgIconProps) => {
    const {type, ...rest} = props
    return <svg
        width="1em"
        height="1em"
        fill="currentColor"
        className={className}
        {...rest}
        xmlns="http://www.w3.org/2000/svg"
        dangerouslySetInnerHTML={{
        __html: `<use xlink:href="#icon-${type}" href="#icon-${type}"></use>`,
        }}>
    </svg>
}

export default SvgIcon;

这样一来,调用SvgIcon组件时,只需要将其type属值的值设置为/src/assets/icons/下的.svg文件名称,就可以将.svg文件渲染到页面上:

// App.tsx
import React from 'react';
import SvgIcon from './components/SvgIcon'
import './App.css';

function App() {
    return (
        <div className="App">
            <header className="App-header">
                <SvgIcon type="facebook" />
                <SvgIcon type="github" />
            </header>
        </div>
    );
}

export default App;

其实你会发现,目前这个效果并不太好。即使我们在SvgIcon组件中显式的设置了fill="currentColor",但Icon颜色并没有根据当前组件color颜色来改变SVG图标颜色。这就要是在/src/assets/icons目录下的.svg源文件中的SVG元素上有显式设置fill的值:

// src/assets/icons/alipay.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1598491090685" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5634" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
    <defs>
        <style type="text/css"></style>
    </defs>
    <path d="M578.656 651.648S512 704.96 487.776 718.944a300.512 300.512 0 0 1-59.104 26.08 247.808 247.808 0 0 1-46.88 10.688c-13.408 1.472-24.512 2.4-33.312 2.848a7.232 7.232 0 0 1-3.136 0.64h-10.08a249.92 249.92 0 0 1-65.088-8.224 164.768 164.768 0 0 1-53.12-24.192 117.856 117.856 0 0 1-35.84-40.256c-8.832-16.16-13.216-34.912-13.216-56.288 0.416-18.432 5.44-35.2 15.04-50.304a133.504 133.504 0 0 1 37.44-38.4 177.536 177.536 0 0 1 50.976-23.904 172.384 172.384 0 0 1 56.288-6.88c18.432 0.832 36.256 3.008 53.44 6.56a485.44 485.44 0 0 1 49.376 12.928c15.712 5.024 30.592 10.464 44.64 16.32 14.08 5.92 27.36 11.552 39.936 17.024a615.04 615.04 0 0 0 32.704 12.576c12.16-15.52 22.4-30.72 30.816-45.6a473.504 473.504 0 0 0 33.344-72c2.944-8.384 4.8-14.24 5.664-17.6h-272.96v-30.208H473.6v-69.76H294.368v-30.208h179.264v-56.64c0-3.744 2.08-6.784 6.272-9.088 4.192-2.304 9.024-3.872 14.464-4.736 6.304-1.248 13.44-1.888 21.376-1.888h48.416v72.32h184.288v30.208H564.16v69.792h146.432l0.096-0.64v0.64h-0.096c-2.944 18.688-7.936 38.4-14.976 59.136a455.52 455.52 0 0 1-26.112 61.632 432.96 432.96 0 0 1-45.6 71.04s144.32 69.088 296.704 93.376C945.888 639.84 960 577.536 960 512c0-247.424-200.576-448-448-448S64 264.576 64 512c0 247.392 200.576 448 448 448 153.472 0 288.896-77.184 369.664-194.848-82.048-17.888-169.216-54.08-303.04-113.504zM224 621.12c-1.696 76.704 85.632 82.4 99.104 82.816 44.544 1.344 80.48-15.36 108.48-31.872 27.968-16.512 73.632-59.2 75.36-60.64 1.664-1.472 3.36-3.04 5.024-4.704-12.224-6.72-24.224-12.864-36-18.528-11.776-5.632-71.68-37.6-124.8-43.04C250.496 534.784 224.512 597.824 224 621.12z" fill="#181818" p-id="5635"></path>
</svg>

如果要达到fill="currentColor"让SVG图标颜色能根据color颜色设置,需要将<path>中的fill的值去掉,或者也显式设置为fill="currentColor"。换句话说,如果你用到的SVG图标多的话,人肉操作也是很大的工作量,这个时候我们可以通过svgo-loader来帮我们处理,而且它还能帮助我们对SVG源码做优化。

使用svgo-loader需要先安装svgosvgo-loader:

» npm install svgo svgo-loader --save-dev

同时在项目根目录下创建svgo相关的配置文件,比如svgo-config.json:

{
    "plugins": [
        { "cleanupAttrs": true },
        { "cleanupEnableBackground": true },
        { "cleanupIDs": true },
        { "cleanupListOfValues": true },
        { "cleanupNumericValues": true },
        { "collapseGroups": true },
        { "convertColors": true },
        { "convertPathData": true },
        { "convertShapeToPath": true },
        { "convertStyleToAttrs": true },
        { "convertTransform": true },
        { "mergePaths": true },
        { "removeComments": true },
        { "removeDesc": true },
        { "removeDimensions": true },
        { "removeDoctype": true },
        { "removeEditorsNSData": true },
        { "removeEmptyAttrs": true },
        { "removeEmptyContainers": true },
        { "removeEmptyText": true },
        { "removeHiddenElems": true },
        { "removeMetadata": true },
        { "removeNonInheritableGroupAttrs": true },
        { "removeRasterImages": true },
        { "removeTitle": true },
        { "removeUnknownsAndDefaults": true },
        { "removeUselessDefs": true },
        { "removeUnusedNS": true },
        { "removeUselessStrokeAndFill": true },
        {
            "removeAttrs": { "attrs": "fill"}
        },
        { "removeXMLProcInst": true },
        { "removeStyleElement": true },
        { "removeUnknownsAndDefaults": true},
        { "sortAttrs": true }
    ]
}

最后别忘了修改webpack.config.js的配置:

const svgoConfig = require('../svgo-config.json');

module: {
    rules: [
        {
             oneOf: [
                 {
                    test: /\.svg$/,
                    use: [
                        {
                            loader:  require.resolve('svg-sprite-loader'), 
                            options: { 
                                symbolId: 'icon-[name]'
                            } 
                        },
                        {
                            loader: 'svgo-loader',
                            options: svgoConfig,
                        }
                    ]
                },
             ]
        }
    ]
}

重新执行npm run start之后,你将看到的效果如下:

在此基础上,我们还可以通过CSS来调整SVG 图标大小:

<SvgIcon type="facebook" className="icon__facebook"/>
<SvgIcon type="github" className="icon__github" />

// app.css
.icon__facebook {
    font-size: 10vw;
}

.icon__github {
    font-size: 20vw;
    color: #f36;
}

这个时候你看以的效果会像下图这样:

其实基于svg-sprite-loader还可以用更简单地方式来构建SVG Sprites。接下来我们就来看svg-sprite-loader的另一种使用方式。我们首先在src/目录下构建一个Icon.js的文件,然后输入下面代码:

// src/Icon.js

import React from 'react';
const files = require.context('!svg-sprite-loader!./assets/icons', false, /.*\.svg$/);
files.keys().forEach(files);

const Icon = (props) => {
    const { type, className = '', ...rest } = props

    return <svg 
        className={`icon icon__${className}`} 
        width="1em" 
        height="1em" 
        fill="currentColor" 
        {...rest}
    >
        <use xlinkHref={`#${type}`}></use>
    </svg>
};

export default Icon;

有了这个Icon模板,我们就可以将其当作Icon组件,并且在使用SVG图标的地方引入该组件,比如:

// App.tsx

import React from 'react';
import './App.css';

import Icon from './Icon'

function App() {
    return (
        <div className="App">
            <header className="App-header">
                <Icon type="facebook" />
                <Icon type="wechat" />
            </header>
        </div>
    );
}

export default App;

这个时候,你在浏览器中看到的效果如下:

从效果上来看,同样遇到前面碰到的现象,那就是fill="currentColor"并没有起到什么效果,其中原因是一样的。我们可以使用SVGO工具帮助我们快速处理和优化SVG代码。而且还可以使用CSS来给SVG图标设置样式,比如图标的颜色、大小等:

.icon__facebook {
    font-size: 20vw;
    color: #f90;
}

.icon__wechat {
    font-size: 30vw;
    color: #f36;
}

这个时候Icon变成下图这样了:

SVGR构建SVG图标系统

我们在《SVG在React中的运用》一文中提到过SVGR可以自动将.svg文件转换为React组件。这里要提到的是,我们还可以使用SVGR的高级模板来构建SVG图标系统。如果你对这方面感兴趣的话,可以阅读@winkerVSbecks的《React Icon System》一文。

基于Node服务构建SVG图标系统

@steveschoger使用Node相关服务构建了一个SVG图标系统,即 Heroicons。该系统提供了两百多个SVG图标,可以直接将.svg文件转换成JSX(也可以理解成React组件):

Heroicons对应的源码可以在GitHub上获取

在Github仓库中提供了React和Vue两个版本。我们也可以按照这种方式来借助Node服务来构建SVG图标系统。

Font Awesome 图标系统

Font Awesome 是社区中非常优势的图标库,而且是最有名的字体图标库,即 大家使用的时候,更喜欢使用字体图标的方式来使用Font Awesome

如果你是基于React框架来开发项目的话,希望在项目中使用Font Awesome的话,除了以往的方式(引入字体),还可以React组件,即 React版本Font Awesome。该版本是由Font Awesome团队创建的一个React组件。不过它包括了免费专业等多个版本。除此之外,它还有Regular(普通)、Light(线性)和 Solid(加粗)等版本。大家使用的时候,可以根据自己需要的版本安装对应的包:

// Font Awesome的基础包
» npm i -S @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/react-fontawesome

// Regular Icons
// 免费版本
» npm i -S @fortawesome/free-regular-svg-icons

// 专业版本
» npm i -S @fortawesome/pro-regular-svg-icons

// Light Icons
» npm i -S @fortawesome/pro-light-svg-icons

// Solid Icons
» npm i -S @fortawesome/free-solid-svg-icons
» npm i -S @fortawesome/pro-solid-svg-icons

// Duotone icons
» npm i -S @fortawesome/pro-duotone-svg-icons

// Brand icons
» npm i -S @fortawesome/free-brands-svg-icons

在需要使用的地方,引入相应的图标组件即可:

// App.tsx
import React from 'react';
import './App.css';

import { faHome, faAppleAlt } from "@fortawesome/free-solid-svg-icons";

import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

function App() {
    return (
        <div className="App">
            <header className="App-header">
                <FontAwesomeIcon icon={faHome} />
                <FontAwesomeIcon icon={faAppleAlt} />
            </header>
        </div>
    );
}

export default App;

渲染出来的结果如下图所示:

使用<FontAwesomeIcon />组件也是将内联SVG代码的方式:

其中传给<FontAwesomeIcon />icon的值对应的就是图标的类名,比如<i class="fas fa-apple-alt"></i>fa-apple-alt换成faAppleAlt

<FontAwesomeIcon icon={faHome} />

另外,基于这个组件还可以扩展自己的图标,有关于这方面更详细的介绍可以阅读@Chris on Code的《How To Use Font Awesome 5 with React》一文。

小结

结合《SVG在React中的运用》一文,和大家一起探讨了在React中怎么使用SVG图标。换句话说,在React开好体系下,除了可以使用React自带的方式之外,还可以使用react-svg-loader、SVGR将.svg文件自动转换成React组件,还可以使用svg-sprite-loader构建SVG Sprites,使用Node服务构建自己的图标系统,而且还可以使用React版本的Font Awesome,并且基于该体系扩展自己的SVG图标。

虽然方法都可以很好的帮助我们构建SVG图标系统,但我们在实际使用SVG图标的时候,希望能对SVG图标中的某些部分做一些调整,比如说更改某个路径的颜色,甚至是添加动效等。如果需要满足这些要求的话,前面提到这些方案都有一定的缺陷,也就是说,我们要在React体系中使用自定义或个性化SVG图标(或组件)就需要换过一种模式。有关于这方面的介绍,将在下一篇文章中和大家一起探讨。如果你对这方面感兴趣的话,欢迎持续关注后续的相关更新。如果你在这方面有更多经验或建议,欢迎在下面的评论中与我们共享。