预览
Icon | Vue3xy (chengbotao.github.io)
Icon | Reactxy (chengbotao.github.io)
介绍
基于
Font Awesome免费图标二次封装
Font Awesome | free
// 使用 Icon 组件前置条件需引入一下依赖
import { library } from '@fortawesome/fontawesome-svg-core';
// 可以按需引入或全量引入免费图标
import { fas } from '@fortawesome/free-solid-svg-icons';
library.add(fas);
props属性
更多属性参考
Font Awesome的FontAwesomeIconProps
| 属性名 | 属性类型 | 说明 | 默认值 |
|---|---|---|---|
theme | oneOf "primary" | "danger" | "secondary" | "success" | "info" | "warning" | "light" | "dark" | 设置 Icon 主题 | primary |
className | string | 自定义CSS类名 | - |
icon | IconProp | icon名字 | - |
呈现
Vue3 实现
<template>
<FontAwesomeIcon v-bind="$attrs" :icon="icon" :class="classes"></FontAwesomeIcon>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'XyIcon',
inheritAttrs: false
})
</script>
<script setup lang="ts">
import { computed } from "vue";
import classNames from "classnames";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/vue-fontawesome";
type ThemeProps =
| 'primary'
| 'secondary'
| 'success'
| 'info'
| 'warning'
| 'danger'
| 'light'
| 'dark';
interface IconProps extends Omit<FontAwesomeIconProps, "icon"> {
icon: object | Array<string> | string | IconDefinition
className?: string
theme?: ThemeProps
}
// Props
const props = withDefaults(defineProps<IconProps>(), {
theme: "primary"
});
// computed
const classes = computed(() => {
return classNames("xy-icon", props.className, {
[`xy-icon-${props.theme}`]: props.theme,
});
})
</script>
Vue3 Icon 单元测试
import { render } from '@testing-library/vue';
import Icon from './index';
import { library } from '@fortawesome/fontawesome-svg-core';
import { fas } from '@fortawesome/free-solid-svg-icons';
library.add(fas);
describe('Icon Component', () => {
// 应呈现正确的 icon 组件
test('should render the correct icon', async () => {
const { getByTestId } = render(Icon, {
props: {
icon: 'coffee',
},
attrs: {
'data-testid': 'xyicon',
},
});
const element = getByTestId('xyicon');
expect(element.className).toMatch(/xy-icon/);
});
});
React 实现
import React, { FC } from 'react';
import classNames from 'classnames';
import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
export type ThemeProps =
| 'primary'
| 'secondary'
| 'success'
| 'info'
| 'warning'
| 'danger'
| 'light'
| 'dark';
export interface IconProps extends FontAwesomeIconProps {
/** 设置 Icon 主题 */
theme?: ThemeProps;
/** 自定义 css 类名 */
className?: string;
/** icon 名字 */
icon: IconProp;
}
/**
* Icon 组件
*
*
*/
export const Icon: FC<IconProps> = (props) => {
const { className, theme, ...restProps } = props;
const classes = classNames('xy-icon', className, {
[`xy-icon-${theme}`]: theme,
});
return <FontAwesomeIcon className={classes} {...restProps}></FontAwesomeIcon>;
};
export default Icon;
React Icon 单元测试
import React from 'react';
import { render } from '@testing-library/react';
import Icon, { IconProps } from './icon';
import { library } from '@fortawesome/fontawesome-svg-core';
import { fas } from '@fortawesome/free-solid-svg-icons';
library.add(fas);
describe('Icon Component', () => {
test('should render the correct icon', () => {
const defaultProps: IconProps = {
icon: 'coffee',
};
const wrapper = render(<Icon data-testid="xyicon" {...defaultProps}></Icon>);
const element = wrapper.getByTestId('xyicon');
expect(element).toBeInTheDocument();
expect(element).toHaveClass('xy-icon');
});
});
后记
Font Awesome
Set Up with Vue | Font Awesome Docs
Set Up with React | Font Awesome Docs
Classic Solid Style Icons | Font Awesome
个人博客 | Botaoxy (chengbotao.github.io)
感谢阅读,敬请斧正!