react从零搭建按需加载的svg图标库过程(一)

创建react项目

安装create-react-app:

npm install -g create-react-app 

创建react项目:

npx create-react-app <项目名称>// 注意:名字不能包含大写字母。

进入项目文件夹(我的是demo):

cd demo
npm start

svg-sprite-loader

GitHub:svg-sprite-loader

原理:svg-sprite-loader 会把svg 塞到一个个 symbol 中,合成一个大的 svg。最后将这个大的 svg 放入 body 中。symbol的id如果不特别指定,就是你的文件名。
利用 svg 的 symbol 元素,将每个 icon 包裹在 symbol 中,通过 use 使用该 symbol。
----------摘自《在React中使用SVG和组件化》《使用svg-sprite-loader优化Icon》

在页面上形成这样的元素:(摘自使用svg-sprite-loader优化Icon
我们的每一个 icon 都对应着一个 symbol 元素,这个时候我们就可以在页面使用 svg use 啦。

<body>
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="__SVG_SPRITE_NODE__">
      <symbol xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 1024 1024" id="xxx">// id 是 icon 名
	<!-- 这块是 path 标签 -->
      </symbol>
      <symbol xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 1024 1024" id="xxx">// id 是 icon 名
	<!-- 这块是 path 标签-->
      </symbol>
    </svg>
</body>

安装

npm i svg-sprite-loader -D

配置 webpack.config.js

这一步必须要修改,由于我创建react项目的方式没有暴露webpack配置文件,所以我一开始没有修改。运行后发现页面是空白的,打开控制台发现是因为没有合理加载svg图标,这是因为webpack中本身就有对svg的处理规则,并且file-loader还有一个默认的地址。
在这里插入图片描述
在这里插入图片描述

访问webpack配置文件有两种方式:

  1. 弹出配置文件,但注意这个操作不可逆。一旦弹出,就无法回去。
npm run eject

成功后会出现一个 config 文件夹:
在这里插入图片描述

  1. 如果不想弹出,只想查看配置,可以在这个目录找到:
/node_modules/react-scripts/config

在配置文件中添加如下配置:

{
    
    
              test: /\.svg$/,
              use: [
                {
    
    
                  loader: require.resolve('svg-sprite-loader'), 
                  options: {
    
    
                    //SymbolId:'icon-[name]'  // 这一行可有可无
                  }
                }
              ]
},

这里 SymbolId 这一行可有可无,SymbolId对应的是使用时 use 标签的xlinkHref属性,也就是说如果采用了 SymbolId:‘icon-[name]’ 的配置,那么使用时的语句应该是 “icon-” 开头的;如果没有特别配置 SymbolId, 那么使用的时候用的是下面注释掉的那种方式:
在这里插入图片描述

踩坑: webpack中原来就有对svg文件的处理,我用includeexclude试了好多次都不成功,最后把原来的注释掉了,只保留上面的配置才生效的。。。

重启项目以后,可以在页面看到svg标签了。(因为我这里是整个写完以后才写的这篇文章记录整个过程,所以这里就放后面弄好的截图啦)

在这里插入图片描述
在这里插入图片描述

我期望的用法是这样的:

<Icon name="account" color="red" size={
    
    [50,50]}/>
或者 size={
    
    50} 这样的写法

所以需要三个参数:

  • 名称(name)
  • 颜色(color)
  • 尺寸(size)。

到目前为止,通过名称引入svg图片的需求就可以基本满足了。

size的实现比较简单,就不做太多赘述了(后面的代码中也体现了处理size的过程),直接在svg上添加属性就可以了,举个简单的例子:

return (
    <svg
      width={
    
    200}  // 把这里换成变量就可以了,或者将样式统一放在一个对象里,然后用展开符也行
      height={
    
    200}
      aria-hidden="true"
    >
      <use xlinkHref={
    
    iconName} />
    </svg>
  )

Icon组件代码:

import React, {
    
     useMemo, useState, useEffect } from 'react'

const Icon = ({
     
     name,width,height}) => {
    
    

  const [svgModule, setSvgModule] = useState();

  const getSvg = async () => {
    
    
    const svg = await import(`../../icons/svg/${
      
      name}.svg`)
    setSvgModule(svg)
  }
  
  const iconName = useMemo(() => {
    
    
    if (svgModule && svgModule.default) {
    
    
      return `#${
      
      svgModule.default.id}`
    }
  }, [name, svgModule])

  useEffect(() => {
    
    
    getSvg()
  }, [])

  return (
    <svg
      width={
    
    width}
      height={
    
    height}
      aria-hidden="true"
    >
      <use xlinkHref={
    
    iconName} />
    </svg>
  )
}

export default Icon

这里获取 svg 图片的方式是通过传入的 name 去引入的,可以打印看一下的内容(也就理解 svgModule.default.id 是什么意思了):
在这里插入图片描述
在这里插入图片描述

svgo-loader

GitHub:svgo-loader

SVG 文件,尤其是从各种编辑器导出的文件,通常包含大量冗余和无用的信息。这可以包括编辑器元数据、注释、隐藏元素、默认值或非最佳值以及其他可以安全删除或转换而不影响 SVG 渲染结果的内容。
-------摘自在React中使用SVG和组件化

SVGO 将 SVG-as-XML 数据转换为 SVG-as-JS AST 表示形式。然后在所有AST数据项上运行并执行一些操作,最后,SVGO 再将 AST 转换回 SVG-as-XML 数据字符串。
SVGO 是 svg 优化器,包含很多插件。它可以删除和修改SVG元素,折叠内容,移动属性等等。
--------摘自《使用svg-sprite-loader优化Icon》

安装svgo-loader:

npm install svgo-loader

配置 webpack.config.js:

{
    
    
  test: /\.svg$/,
  use: [
    {
    
     loader: 'svg-sprite-loader', options: {
    
    } },
+   {
    
     loader: 'svgo-loader', options: {
    
    
         plugins:[  // 可不加
            {
    
    removeAttrs:{
    
    attrs:'fill'}}//删除svg原本的fill属性,方便修改图标颜色
          ]
        }
      }
   ]
}

引入项目中的 svg 文件会经过 svgo-loader => svg-sprite-loader 的处理。先处理 svg 图像,然后在页面中生成 svg-symbols。-------摘自在React中使用SVG和组件化

颜色的处理比较麻烦,写在下一篇文章了。

下一篇:关于svg颜色部分的处理

猜你喜欢

转载自blog.csdn.net/Charonmomo/article/details/129666438