引言
Icon 组件是组件库中最基础、使用频率最高的组件之一。在这篇文章中,我将详细介绍 LPieces-UI 的 Icon 组件设计思路和实现细节。
你将学到:
- SVG 图标在 Vue3 组件中的应用
- Icon 组件的 API 设计
- TypeScript 类型定义
- 样式封装方案
一、需求分析
1.1 核心功能
| 功能 | 说明 |
|---|---|
| 图标展示 | 支持 SVG 图标渲染 |
| 尺寸控制 | 支持 small / default / large 三种尺寸 |
| 颜色控制 | 支持自定义颜色 |
| 旋转动画 | 支持加载状态的旋转动画 |
1.2 API 设计
vue
<lp-icon icon="search" />
<lp-icon icon="user" size="large" color="#409EFF" />
<lp-icon icon="loading" spin />
二、组件实现
2.1 类型定义
packages/components/Icon/types.ts:
typescript
export type IconSize = 'small' | 'default' | 'large'
export interface IconProps {
icon?: string
size?: IconSize
color?: string
spin?: boolean
}
2.2 组件源码
packages/components/Icon/Icon.vue:
vue
<script setup lang="ts">
import type { IconProps } from './types'
import { computed } from 'vue'
const props = withDefaults(defineProps<IconProps>(), {
size: 'default',
spin: false
})
const iconStyle = computed(() => ({
fontSize: props.size === 'small' ? '14px' : props.size === 'large' ? '20px' : '16px',
color: props.color,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center'
}))
const iconClass = computed(() => [
'lp-icon',
{ 'is-spin': props.spin }
])
</script>
<template>
<i :class="iconClass" :style="iconStyle">
<slot />
</i>
</template>
<style scoped>
.lp-icon {
vertical-align: middle;
}
.is-spin {
animation: lp-icon-spin 1s linear infinite;
}
@keyframes lp-icon-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>
三、使用 FontAwesome 图标
为了提供丰富的图标选择,LPieces-UI 集成了 FontAwesome。
3.1 安装依赖
bash
pnpm add @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/vue-fontawesome
3.2 更新 Icon 组件
vue
<script setup lang="ts">
import type { IconProps } from './types'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { computed } from 'vue'
const props = withDefaults(defineProps<IconProps>(), {
size: 'default',
spin: false
})
const iconStyle = computed(() => ({
fontSize: props.size === 'small' ? '14px' : props.size === 'large' ? '20px' : '16px',
color: props.color
}))
</script>
<template>
<span class="lp-icon" :style="iconStyle">
<FontAwesomeIcon v-if="icon" :icon="icon" :spin="spin" />
<slot v-else />
</span>
</template>
四、组件导出
packages/components/Icon/index.ts:
typescript
import { withInstall } from '@lpieces-ui/utils'
import Icon from './Icon.vue'
export const LpIcon = withInstall(Icon)
五、使用示例
vue
<template>
<div>
<h3>基础用法</h3>
<lp-icon icon="user" />
<h3>尺寸</h3>
<lp-icon icon="search" size="small" />
<lp-icon icon="search" size="default" />
<lp-icon icon="search" size="large" />
<h3>颜色</h3>
<lp-icon icon="heart" color="#f56c6c" />
<lp-icon icon="star" color="#e6a23c" />
<h3>旋转动画</h3>
<lp-icon icon="spinner" spin />
</div>
</template>
六、总结
Icon 组件虽然简单,但它展示了组件库开发的核心思路:
- ✅ TypeScript 类型定义
- ✅ Props API 设计
- ✅ 样式封装
- ✅ 第三方库集成