Icon组件

需求分析

Icon组件的核心其实就是一个i标签,引入了一些字体图标,再添加一些样式,当然也可以自定义css样式。按照惯例,我们先来写一下Icon组件所需要的属性以及他们的类型有哪些。除此之外呢,我们还要找一些合适的字体图标,那么@fortawesome/fontawesome-svg-core@fortawesome/free-solid-svg-icons@fortawesome/vue-fontawesome就很适合我们这个Icon组件。

代码实现

先来看看Icon组件可以接受哪些属性:

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
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core'
export interface IconProps {
border?: boolean
fixedWidth?: boolean
flip?: 'horizontal' | 'vertical' | 'both'
icon: object | Array<string> | string | IconDefinition
mask?: object | Array<string> | string
listItem?: boolean
pull?: 'right' | 'left'
pulse?: boolean
rotation?: 90 | 180 | 270 | '90' | '180' | '270'
swapOpacity?: boolean
size?: '2xs' | 'xs' | 'sm' | 'lg' | 'xl' | '2xl' | '1x' | '2x' | '3x' | '4x' | '5x' | '6x' | '7x' | '8x' | '9x' | '10x'
spin?: boolean
transform?: object | string
symbol?: boolean | string
title?: string
inverse?: boolean
bounce?: boolean
shake?: boolean
beat?: boolean
fade?: boolean
beatFade?: boolean
spinPulse?: boolean
spinReverse?: boolean
type?: 'primary'| 'success'| 'warning'| 'danger'| 'info'
color?: string
}

组件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<i class="tm-icon" :class="{[`tm-icon--${type}`]: type}" :style="customStyles" v-bind="$attrs">
<font-awesome-icon v-bind="filteredProps"></font-awesome-icon>
</i>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { omit } from 'lodash-es'
import type { IconProps } from './types'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
defineOptions({
name: 'TmIcon',
inheritAttrs: false
})
const props = defineProps<IconProps>()
const filteredProps = computed(() => omit(props, ['type', 'color']))
const customStyles = computed(() => {
return props.color ? { color: props.color } : {}
})
</script>

Icon组件的代码结构也很简单,它的核心就是一个<i>标签,添加了一些属性和自定义的样式。

引入字体图标库

1
2
3
4
import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'

library.add(fas)

在其他组件中使用Icon组件

在Button组件中使用

1
2
3
<!-- Button.vue -->
<Icon v-if="loading" :icon="spinner" spin></Icon>
<Icon v-if="icon" :icon="icon"></Icon>
1
2
3
4
5
6
7
8
<!-- 在App.vue中引入Button组件 -->
<script lang="ts" setup>
import TmButton from '@/components/Button/Button.vue'
</script>

<template>
<TmButton loading size="large"></TmButton>
</template>