React项目使用SVG

1,020 阅读1分钟

简单介绍下SVG格式图标在React项目中的使用


首先要下载svg格式图标,推荐使用 iconfont.cn,下载之后,直接当图片使用也可以,但是作为图片使用就不方便更改它的颜色,对于活动按钮和非活动按钮的区分不是很好。

作为svg文件使用之前,我们需要做一些准备工作:安装loader,配置webpack

安装: 需要安装svg-sprite-loadersvgo-loader,执行命令yarn add svg-sprite-loader svgo-loader -D。"svgo"的"o"意思是optimize, 优化的意思,比如有些svg文件自身就有fill属性,导致我们后期给他添加颜色失败,就可以通过svgo-loader来解决这个问题

webpack配置: 需要在webpack.config.js中配置,但是在项目中找不到,查看React官方文档,发现它默认是隐藏的,通过命令yarn eject调出配置文件,调出之后就不能再隐藏了

具体配置: webpack.config.js

{
  test: /\.svg$/,
  use: [
    {loader: 'svg-sprite-loader', options: {}},
    {
      loader: 'svgo-loader', options: {
        plugins: [
          {removeAttrs: {attrs: 'fill'}} // 意思是移除fill属性
        ]
      }
    }
  ]
},

使用:

  1. TreeShaking:用import引入.svg需要使用一下,否则就会TreeShaking,被删掉,改用require,因为TreeShaking不适用于require
require('icons/money.svg');
require('icons/tag.svg');
require('icons/chart.svg');
  1. 使用svg图标,代码示例:xlink
<li>
  <svg className={"icon"}>
    <use xlinkHref="#money"/>
  </svg>
  <Link to="/tags">标签</Link>
</li>
  1. 发现每个svg都需要require引入一次,当svg多的时候,就会有很多重复的require,我们可以将其封装成一个组件,通过props传入不同的文件名,来显示不同的svg图标
  • 这里使用到了classnames插件,方便动态的提供样式。安装方法为:yarn add classnames@2.2.6; yarn add --dev @types/classnames@2.2.6
import React from 'react';
import cs from 'classnames'

let importAll = (requireContext: __WebpackModuleApi.RequireContext) => 
    requireContext.keys().forEach(requireContext);
try {importAll(require.context('icons', true, /\.svg$/));} 
catch (error) {console.log(error);}


type Props ={
  name?: string;
} & React.SVGAttributes<SVGElement>

const Icon = (props: Props)=>{
  const {name, children, className, ...rest} = props;
  return (
    <svg className={cs('icon', className)} {...rest}>
      {props.name && <use xlinkHref={'#' + props.name} />}
    </svg>
  )
}

export default Icon;

说明:require.context是由webpack实现的

注意:因为没有安装webpack环境的TS依赖,上面的代码会报错,安装命令:yarn add --dev @types/webpack-env@1.15.1

  1. 封装为Icon组件后,就可以只用一个Icon标签来使用svg了
...
import Icon from './Icon';
...
<li>
  <NavLink to="/tags" activeClassName="selected">
    <Icon name="tag"/>
    <span>标签</span>
  </NavLink>
</li>
<li>
  <NavLink to="/money" activeClassName="selected">
    <Icon name="money"/>
    <span>记账</span>
  </NavLink>
</li>
<li>
  <NavLink to="/statistics" activeClassName="selected">
    <Icon name="chart"/>
    <span>统计</span>
  </NavLink>
</li>
...