图标处理方案
# Icon 图标处理方案:SvgIcon
在我们的项目中所使用的 icon
图标,一共分为两类:
element-plus
的图标- 自定义的
svg
图标
这也是通常情况下企业级项目开发时,所遇到的一种常见情况。
element-plus
的图标:通过 el-icon
来进行显示
自定义图标:需要一个自定义的组件,来显示我们自定义的 svg
图标。
通用解决方案:需要自定义组件处理 自定义 svg
图标的形式
对于这个组件的话,它就需要拥有两种能力:
- 显示外部
svg
图标 - 显示项目内的
svg
图标
# 处理外部图标
创建 components/SvgIcon/index.vue
:
<template>
<div
v-if="isExternal"
:style="styleExternalIcon"
class="svg-external-icon svg-icon"
:class="className"
/>
<svg v-else class="svg-icon" :class="className" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script setup>
import { isExternal as external } from '@/utils/validate'
import { defineProps, computed } from 'vue'
const props = defineProps({
// icon 图标
icon: {
type: String,
required: true
},
// 图标类名
className: {
type: String,
default: ''
}
})
/**
* 判断是否为外部图标
*/
const isExternal = computed(() => external(props.icon))
/**
* 外部图标样式
*/
const styleExternalIcon = computed(() => ({
mask: `url(${props.icon}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.icon}) no-repeat 50% 50%`
}))
/**
* 项目内图标
*/
const iconName = computed(() => `#icon-${props.icon}`)
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
创建 utils/validate.js
:
/**
* 判断是否为外部资源
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
1
2
3
4
5
6
2
3
4
5
6
在 views/login/index.vue
中使用 外部 svg
(https://res.lgdsunday.club/user.svg
):
<span class="svg-container">
<svg-icon icon="https://res.lgdsunday.club/user.svg"></svg-icon>
</span>
1
2
3
2
3
# 处理内部 svg 图标显示
首先导入所有的
svg
图标在
icons
下创建index.js
文件,该文件中需要完成两件事情:- 导入所有的
svg
图标 - 完成
SvgIcon
的全局注册
- 导入所有的
得出以下代码:
import SvgIcon from '@/components/SvgIcon' // https://webpack.docschina.org/guides/dependency-management/#requirecontext // 通过 require.context() 函数来创建自己的 context const svgRequire = require.context('./svg', false, /\.svg$/) // 此时返回一个 require 的函数,可以接受一个 request 的参数,用于 require 的导入。 // 该函数提供了三个属性,可以通过 require.keys() 获取到所有的 svg 图标 // 遍历图标,把图标作为 request 传入到 require 导入函数中,完成本地 svg 图标的导入 svgRequire.keys().forEach(svgIcon => svgRequire(svgIcon)) export default app => { app.component('svg-icon', SvgIcon) }
1
2
3
4
5
6
7
8
9
10
11
12
13在
main.js
中引入该文件... // 导入 svgIcon import installIcons from '@/icons' ... installIcons(app) ...
1
2
3
4
5
6删除
views/login
下 局部导入SvgIcon
的代码在
login/index.vue
中使用SvgIcon
引入本地svg
// 用户名 <svg-icon icon="user" /> // 密码 <svg-icon icon="password" /> // 眼睛 <svg-icon icon="eye" />
1
2
3
4
5
6此时 处理内容
svg
图标的代码 已经完成
打开浏览器,我们发现 图标依然无法展示! 这又是因为什么原因呢?
# 使用 svg-sprite-loader 处理 svg 图标
svg-sprite-loader (opens new window) 是 webpack
中专门用来处理 svg
图标的一个 loader
,在上一节中我们的图标之所有没有展示,就是因为我们缺少该 loader
。
下载该
laoder
执行
npm i --save-dev [email protected]
1创建
vue.config.js
文件,新增如下配置:const path = require('path') function resolve(dir) { return path.join(__dirname, dir) } // https://cli.vuejs.org/zh/guide/webpack.html#%E7%AE%80%E5%8D%95%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F module.exports = { chainWebpack(config) { // 设置 svg-sprite-loader 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() } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
上次更新: 2024/08/14, 04:14:33