如何优雅的封装svg-icon并运用到项目中(webpack和vite)

先看一下封装好的使用方式: 这里先讲vue-cli项目的相关配置,vite项目对应的插件和配置教程在下方,需要的小伙伴可以直接往下翻

一. webpack项目配置流程

1. 安装依赖

首先需要在我们的项目中安装svg-sprite-loader这个loader,svg-sprite-loader是一个Webpack loader,用于将多个SVG文件打包成一个雪碧图(sprite)。它可以帮助优化网页性能,减少HTTP请求的数量,同时提供了一种方便的方式来管理和使用SVG图标

优点:

预加载 在项目运行时就生成所有图标,只需操作一次 dom高性能 内置缓存,仅当文件被修改时才会重新生成

接下来我们开始安装

(1).安装和配置 svg-sprite-loader:

npm i svg-sprite-loader -D

# 或

pnpm install svg-sprite-loader -D

# 或

yarn add svg-sprite-loader -D

(2).填写配置

如果是vue-cli搭建的项目,则需要在vue.config.js中添加:

const path = require('path')

// 项目的其他配置项,这里进行省略......

module.exports = defineConfig({

// 项目的其他配置项,这里进行省略......

chainWebpack: (config) => {

config.module.rule('svg').exclude.add(resolve('src/icons')).end()

config.module

.rule('icons')

.test(/\.svg$/)

.include.add(resolve('src/icons'))

.end()

.use('svg-sprite-loader')

.loader('svg-sprite-loader')

.options({

symbolId: 'icon-[name]'

})

.end()

}

})

原生webpack的项目,则需要在webpack.config.js中添加对应的loader配置:

注意:url-loader 中要将 icons 文件夹排除, 不让 url-loader 处理该文件夹

// 其他配置项,这里进行省略......

module.exports = {

// 其他配置项,这里进行省略......

module: {

// 其他配置项,这里进行省略......

rules: [

// 其他loader,这里进行省略......

{

test: /\.svg$/,

loader: 'svg-sprite-loader',

include: [resolve('src/icons')],

options: {

symbolId: 'icon-[name]'

}

},

{

test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

loader: 'url-loader',

options: {

limit: 10000,

name: utils.assetsPath('img/[name].[hash:7].[ext]')

},

exclude: [resolve('src/icons')]

}

]

}

}

2. 新建组件和目录

(1).封装svg-icon组件

components 中新建组件 SvgIcon.vue:

vue3:

如果是vue2项目,可以使用下面这个组件:

(2).在src下icons文件夹下新建svg目录和index.js文件

目录结构:

src/icons

- /svg # svg目录保存图标

- /index.ts # 注册全局组件

新建的index.ts:

// 引入封装好的SvgIcon组件

import SvgIcon from '@/components/SvgIcon/index.vue' // svg component

import type { App } from 'vue'

// 全局注册

export const registerSvgIcon = (app: App): void => {

app.component('svg-icon', SvgIcon)

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

// eslint-disable-next-line

const requireAll = (requireContext: any) =>

requireContext.keys().map(requireContext)

requireAll(req)

}

然后在项目的main.ts中引入:

main.ts部分代码

// 其他导入,这里省略......

import { createApp } from 'vue'

import App from './App.vue'

import { registerSvgIcon } from '@/icons'

const app = createApp(App).use(router).use(i18n).use(pinia)

registerSvgIcon(app)

app.mount('#app')

/* vue2直接Vue.use(registerSvgIcon)即可 */

3. 最后我们就可以在项目中全局使用了

icon-class传入的就是svg目录下文件的文件名,比如目录之放一个有个goBack.svg文件,我们就可以按照下面的方式使用。

也可以传入路径或者图片链接的方式,当然这种方式上面vue2对应的组件没有进行封装,感兴趣的小伙伴可以自己琢磨一下

二. vite项目配置流程

1. 安装

yarn add vite-plugin-svg-icons -D

# 或

npm i vite-plugin-svg-icons -D

# 或

pnpm install vite-plugin-svg-icons -D

2. 配置插件

在vite.config.ts 中的配置插件

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'

import path from 'path'

export default () => {

return {

plugins: [

createSvgIconsPlugin({

// 指定需要缓存的图标文件夹

iconDirs: [path.resolve(process.cwd(), 'src/icons')],

// 指定symbolId格式

symbolId: 'icon-[dir]-[name]',

/**

* 自定义插入位置

* @default: body-last

*/

inject?: 'body-last' | 'body-first'

/**

* custom dom id

* @default: __svg__icons__dom__

*/

customDomId: '__svg__icons__dom__',

}),

],

}

}

在 src/main.ts 内引入注册脚本

import 'virtual:svg-icons-register'

在src目录下新建icons文件夹用来存放svg图表

注意:不同与上面webpack的插件配置方式,这里不需要我们手动创建导入的js文件,在上面配置项的iconDirs里指定目录即可,比如上面配置了'src/icons'这个目录,只需要把svg图标全部存放到这个目录即可

3. 封装vue组件

创建svg-icon.vue组件:

和上面wabpack不同的是,目录可以更深层级的嵌套,比如icon目录下有个dir子目录,子目录之下放demo.svg文件,组件内就可以直接使用目录名-文件名的方式,比如:name="dir-demo"

icons 目录结构:

# src/icons

- icon1.svg

- icon2.svg

- icon3.svg

- dir/icon1.svg

其他组件中使用:

也可以注册为全局组件,不用每次都导入: 在components目录下新建一个index.ts 文件

// 引入项目中的全部全局组件

import SvgIcon from './svgIcon/index.vue'

//其他组件,这里省略...

// 组装成一个对象

const allGlobalComponents: any = {

SvgIcon,

//其他组件,这里省略...

}

// 对外暴露插件对象,在main.ts中引入后,直接自动调用install方法

export default {

install(app: any) {

// 循环注册所有的全局组件

Object.keys(allGlobalComponents).forEach((componentName) => {

app.component(componentName, allGlobalComponents[componentName])

})

},

}

main.ts中导入并use:

import { globalComponents } from '@/components'

reateApp(App).use(globalComponents).mount('#app')

4. 封装React组件

(1). /src/components目录下新建SvgIcon.jsx组件:

export default function SvgIcon({

name,

prefix = 'icon',

color = '#333',

width = '16px',

height = '16px',

...props

}) {

const symbolId = `#${prefix}-${name}`

return (

)

}

5. 获取所有 SymbolId

import ids from 'virtual:svg-icons-names'

// => ['icon-icon1','icon-icon2','icon-icon3']

6. 配置说明

参数类型默认值说明iconDirsstring[]-需要生成雪碧图的图标文件夹symbolIdstringicon-[dir]-[name]svg 的 symbolId 格式,见下方说明svgoOptionsboolean|SvgoOptionstruesvg 压缩配置,可以是对象Optionsinjectstringbody-lastsvgDom 默认插入的位置,可选body-firstcustomDomIdstring__svg__icons__dom__svgDom 插入节点的 ID

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。