Icon
# 1. Icon 如何使用
实战项目主要采用两种 Icon 使用方式:自定义 SVG 图标和 Ant Design Vue 图标。
# 1.1 自定义 SVG 图标
对于项目特有的业务图标或定制化图标,项目将其作为 SVG 文件引入,并通过一个封装的 <Icon> 组件进行使用。
使用示例:
vue
<template>
<div>
<!-- 使用名为 "menu-dashboard" 的自定义图标 -->
<icon type="menu-dashboard" />
<!-- 在配置中引用图标 -->
<icon :type="item.meta.icon" />
<!-- 带有默认图标的用法 -->
<icon :type="{ icon: getIcon(item.path), defaultIcon: 'star' }" />
</div>
</template>
<script>
// ...
export default {
// ...
}
</script>
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
说明:
自定义 SVG 图标通过 <icon> 组件的 type 属性指定,type 的值对应 SVG 文件的名称(不包含 .svg 后缀)。
这些 SVG 文件通常放置在 src/components/Icon 或 scope/assets 等目录下,通过 webpack 配置统一处理。
# 1.2 Ant Design Vue 图标
对于一些通用的、系统级的图标(如箭头、加载、删除等),项目直接使用 Ant Design Vue 提供的 <a-icon> 组件。
使用示例:
vue
<template>
<div>
<!-- 使用 Ant Design Vue 的向下箭头图标 -->
<a-icon type="down" />
<!-- 使用 Ant Design Vue 的向上箭头图标 -->
<a-icon type="up" />
</div>
</template>
<script>
// ...
export default {
// ...
}
</script>
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
说明:
- Ant Design Vue 图标通过 <a-icon> 组件的 type 属性指定,其 type 值遵循 Ant Design Vue 的图标命名规范。
# 2. Icon 如何封装
项目的自定义 SVG 图标通过 vue.config.js 中的 webpack 配置和自定义的 <Icon> 组件进行封装。
# 2.1 vue.config.js 中的 webpack 配置
在 vue.config.js 中,通过 chainWebpack 配置对 SVG 文件进行了特殊处理,以生成 SVG 雪碧图。
javascript
chainWebpack: (config) => {
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule.include.add(resolve('./src/components/Icon')) // 包含自定义图标路径
svgRule.include.add(resolve('./scope/assets')) // 包含自定义图标路径
svgRule
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'oc-[name]', // 雪碧图中每个 SVG 的 ID 前缀
extract: true,
spriteFilename: 'sprite.svg', // 生成的 SVG 雪碧图文件名
})
.end()
.use('svgo-loader')
.loader('svgo-loader')
.options({
configFile: false, // 不使用默认配置文件
})
.end()
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('./src/components/Icon')) // 排除自定义图标路径,避免被images loader处理
imagesRule.exclude.add(resolve('./scope/assets'))
config.module.rule('images').test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
},
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
配置解析:
svg-sprite-loader: 这个 loader 负责将多个 SVG 文件合并成一个 SVG 雪碧图(sprite)。它会为每个 SVG 生成一个 <symbol> 标签,并将其 id 设置为 symbolId 选项中定义的格式(例如 oc-menu-dashboard)。
svgo-loader: 在 SVG 合并之前,svgo-loader 会对 SVG 文件进行优化,移除不必要的代码,减小文件大小。
imagesRule.exclude: 通过将自定义 SVG 图标的路径从 images 规则中排除,确保这些 SVG 文件只由 svg-sprite-loader 处理,而不是作为普通的图片文件。
# 2.2 自定义 <Icon> 组件
项目中存在一个自定义的 <Icon> Vue 组件(通常在 src/components/Icon/index.vue 附近)。这个组件接收 type 属性,并根据 type 的值渲染对应的 SVG 雪碧图中的图标。
vue
<template>
<svg class="icon" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
export default {
name: 'Icon',
props: {
type: {
type: [String, Object],
required: true,
},
},
computed: {
iconName() {
// 处理传入的type属性,例如:
// 如果type是字符串 'menu-dashboard',则返回 '#oc-menu-dashboard'
// 如果type是对象 { icon: 'some-icon', defaultIcon: 'star' }
// 则根据逻辑返回 '#oc-some-icon' 或 '#oc-star'
if (typeof this.type === 'string') {
return `#oc-${this.type}`
} else if (typeof this.type === 'object' && this.type.icon) {
return `#oc-${this.type.icon}`
} else if (typeof this.type === 'object' && this.type.defaultIcon) {
return `#oc-${this.type.defaultIcon}`
}
return '' // 或其他默认处理
},
},
}
</script>
<style scoped>
.icon {
width: 1em; /* 根据需要调整 */
height: 1em; /* 根据需要调整 */
vertical-align: -0.15em; /* 保持对齐 */
fill: currentColor; /* 图标颜色继承父元素颜色 */
overflow: hidden;
}
</style>
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
说明:
<Icon> 组件内部通过 <svg><use></use></svg> 标签来引用 SVG 雪碧图中的具体图标。
xlink:href 属性的值通常是 # 加上雪碧图中 SVG <symbol> 的 id。
# 3. 优缺点
# 3.1 优点 (Advantages)
减少 HTTP 请求:所有自定义 SVG 图标被打包成一个雪碧图文件,减少了浏览器的网络请求数量,提高了页面加载性能。
灵活的样式控制:SVG 是矢量图,可以通过 CSS 灵活控制图标的颜色、大小、旋转等属性,而不会失真。
高分辨率支持:作为矢量图,SVG 在任何分辨率和缩放比例下都能保持清晰,无需为不同 DPI 设备准备多套图标。
便于管理和维护:
通过自定义 <Icon> 组件统一管理图标的引用,使得代码更具可读性和一致性。
在 vue.config.js 中集中配置 SVG 处理,方便统一优化和维护。
可以方便地将图标名称作为字符串在各种配置(如菜单配置)中使用。
- 与 UI 库良好结合:项目可以在使用自定义品牌图标的同时,方便地集成 Ant Design Vue 提供的丰富通用图标,互不冲突,提高了开发效率。
# 3.2 缺点 (Disadvantages)
构建配置复杂性:需要额外的 webpack 配置(svg-sprite-loader 和 svgo-loader)来处理 SVG 雪碧图,增加了项目的构建配置复杂性。
新增图标流程:每次新增自定义 SVG 图标时,需要确保文件放置在正确目录,并遵循命名约定,以被 webpack 正确打包。
初始加载大小:虽然减少了请求数量,但雪碧图文件在首次加载时可能会相对较大。不过,一旦加载并缓存,后续页面切换时无需再次下载。
调试:在某些情况下,调试 SVG 雪碧图中的单个图标可能比调试独立的 SVG 文件稍微复杂一点,因为所有图标都集中在一个文件中。
总结:
项目的 Icon 策略通过结合 SVG 雪碧图和 Ant Design Vue 图标,实现了自定义图标的灵活管理和高效加载,同时兼顾了通用图标的便捷性。这种策略在性能、可维护性和样式控制方面表现出色,是大型前端项目常用的优秀实践。