如何在Vue/Angular/React中为未注册Font Awesome图标设默认占位图标
全局设置Font Awesome未注册/不存在图标的默认占位图标
问题场景
我通过library方式批量注册了Font Awesome各类Pro图标:
export const faIconsDefinitionsToRegister: IconDefinition[] = [ ...proRegularFaIcons, ...proSolidFaIcons, ...proLightFaIcons, ...proThinFaIcons, ...proDuotoneFaIcons, ]; library.add(...faIconsDefinitionsToRegister) faConfig.defaultPrefix = 'far';
当使用未注册或不存在的图标时(如下列多框架示例),当前会显示空白,我希望全局替换为['fas', 'question']问号图标:
<!-- Angular语法 --> <fa-icon [icon]="['far', 'unknown-icon-name']"></fa-icon> <fa-icon icon="unknown-icon-name"></fa-icon> <!-- Vue语法 --> <fa-icon :icon="['far', 'unknown-icon-name']"></fa-icon> <fa-icon icon="unknown-icon-name"></fa-icon> <!-- React语法 --> <FaIcon icon={['far', 'unknown-icon-name']}></FaIcon> <FaIcon icon="unknown-icon-name"></FaIcon>
要求尽量不使用CSS类实现全局配置。
解决方案
前置准备:注册默认占位图标
首先确保['fas', 'question']已被注册到library中,否则占位图标也会显示空白:
import { faQuestion } from '@fortawesome/free-solid-svg-icons'; export const faIconsDefinitionsToRegister: IconDefinition[] = [ faQuestion, // 新增问号图标注册 ...proRegularFaIcons, ...proSolidFaIcons, ...proLightFaIcons, ...proThinFaIcons, ...proDuotoneFaIcons, ]; library.add(...faIconsDefinitionsToRegister)
Angular 实现
通过自定义指令拦截图标解析逻辑,全局覆盖fa-icon组件的行为:
import { Directive, Input, OnInit } from '@angular/core'; import { FaIconComponent, FaConfig, library } from '@fortawesome/angular-fontawesome'; @Directive({ selector: 'fa-icon' }) export class FaFallbackIconDirective implements OnInit { @Input() icon: any; constructor( private faIconComponent: FaIconComponent, private faConfig: FaConfig ) {} ngOnInit(): void { let iconToCheck = this.icon; // 处理单个图标名称的情况,补全默认前缀 if (typeof iconToCheck === 'string') { iconToCheck = [this.faConfig.defaultPrefix, iconToCheck]; } const [prefix, name] = iconToCheck; // 检查library中是否存在目标图标 const iconExists = library.definitions[prefix]?.hasOwnProperty(name); if (!iconExists) { // 替换为默认问号图标 this.faIconComponent.icon = ['fas', 'question']; } } }
将该指令在根模块中声明,即可全局生效。
Vue 实现
通过全局包装原生fa-icon组件,注入图标校验逻辑:
import { createApp, h } from 'vue'; import { FontAwesomeIcon, library, faConfig } from '@fortawesome/vue-fontawesome'; import App from './App.vue'; const app = createApp(App); // 包装原生组件 app.component('FaIcon', { props: ['icon'], render() { let iconToCheck = this.icon; // 处理单个图标名称的情况 if (typeof iconToCheck === 'string') { iconToCheck = [faConfig.defaultPrefix, iconToCheck]; } const [prefix, name] = iconToCheck; const iconExists = library.definitions[prefix]?.hasOwnProperty(name); return h(FontAwesomeIcon, { icon: iconExists ? this.icon : ['fas', 'question'] }); } }); app.mount('#app');
项目中直接使用<FaIcon>组件即可自动触发占位逻辑。
React 实现
创建自定义包装组件,替代原生FaIcon全局使用:
import { FaIcon as OriginalFaIcon, library, faConfig } from '@fortawesome/react-fontawesome'; import { faQuestion } from '@fortawesome/free-solid-svg-icons'; // 注册占位图标(若之前已注册可省略) library.add(faQuestion); export const FaIcon = ({ icon, ...props }) => { let iconToCheck = icon; // 处理单个图标名称的情况 if (typeof iconToCheck === 'string') { iconToCheck = [faConfig.defaultPrefix, iconToCheck]; } const [prefix, name] = iconToCheck; const iconExists = library.definitions[prefix]?.hasOwnProperty(name); return <OriginalFaIcon icon={iconExists ? icon : ['fas', 'question']} {...props} />; };
后续项目中统一导入并使用这个自定义FaIcon组件。
内容的提问来源于stack exchange,提问作者E-jarod
相关产品推荐
相关产品推荐

