vue3项目中动态加载字体,并解决字体图标显示异常问题

先上效果图
在这里插入图片描述

setIconfont.ts文件代码

// 字体图标 url
// 为什么引入俩个版本的font-awesome图标,因为最新版本的图标需要匹配字体库,单独引入样式文件部分图标会不显示
// 测试发现在引入4.7.0中的样式后所有的图标都可以显示,暂且认为4.7.0版本中有该字体文件
const cssCdnUrlList: Array<string> = [
	'//cdn.bootcdn.net/ajax/libs/font-awesome/6.4.2/css/all.css',
	'//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css',
]
// 第三方 js url
const jsCdnUrlList: Array<string> = []

// 动态批量设置字体图标
export function setCssCdn() {
	if (cssCdnUrlList.length <= 0) return false
	cssCdnUrlList.map((v) => {
		let link = document.createElement('link')
		link.rel = 'stylesheet'
		link.href = v
		link.crossOrigin = 'anonymous'
		document.getElementsByTagName('head')[0].appendChild(link)
	})
}

// 动态批量设置第三方js
export function setJsCdn() {
	if (jsCdnUrlList.length <= 0) return false
	jsCdnUrlList.map((v) => {
		let link = document.createElement('script')
		link.src = v
		document.body.appendChild(link)
	})
}

/**
 * 批量设置字体图标、动态js
 * @method cssCdn 动态批量设置字体图标
 * @method jsCdn 动态批量设置第三方js
 */
const setIntroduction = {
	// 设置css
	cssCdn: () => {
		setCssCdn()
	},
	// 设置js
	jsCdn: () => {
		setJsCdn()
	},
}

// 导出函数方法
export default setIntroduction

getStyleSheets.ts文件代码

import { nextTick } from 'vue'
import * as svg from '@element-plus/icons-vue'

// 获取阿里字体图标
const getAlicdnIconfont = () => {
	return new Promise((resolve, reject) => {
		nextTick(() => {
			const styles: any = document.styleSheets
			let sheetsList = []
			let sheetsIconList = []
			for (let i = 0; i < styles.length; i++) {
				if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) {
					sheetsList.push(styles[i])
				}
			}
			for (let i = 0; i < sheetsList.length; i++) {
				for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
					if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) {
						sheetsIconList.push(
							`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
						)
					}
				}
			}
			if (sheetsIconList.length > 0) resolve(sheetsIconList)
			else reject('未获取到值,请刷新重试')
		})
	})
}

// 初始化获取 css 样式,获取 element plus 自带 svg 图标,增加了 ele- 前缀,使用时:ele-Aim
const getElementPlusIconfont = () => {
	return new Promise((resolve, reject) => {
		nextTick(() => {
			const icons = svg as any
			const sheetsIconList = []
			for (const i in icons) {
				sheetsIconList.push(`ele-${icons[i].name}`)
			}
			if (sheetsIconList.length > 0) resolve(sheetsIconList)
			else reject('未获取到值,请刷新重试')
		})
	})
}

// 初始化获取 css 样式,这里使用 fontawesome 的图标
const getAwesomeIconfont = () => {
	return new Promise((resolve, reject) => {
		nextTick(() => {
			const styles: any = document.styleSheets
			let sheetsList = []
			let sheetsIconList = []
			for (let i = 0; i < styles.length; i++) {
				if (styles[i].href && styles[i].href.indexOf('font-awesome') > -1) {
					sheetsList.push(styles[i])
				}
			}
			for (let i = 0; i < sheetsList.length; i++) {
				for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
					if (
						sheetsList[i].cssRules[j].selectorText &&
						sheetsList[i].cssRules[j].selectorText.indexOf('.fa-') === 0 &&
						sheetsList[i].cssRules[j].selectorText.indexOf(',') === -1
					) {
						if (/::before/.test(sheetsList[i].cssRules[j].selectorText)) {
							sheetsIconList.push(
								`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
							)
						}
					}
				}
			}

			if (sheetsIconList.length > 0) resolve(Array.from(new Set(sheetsIconList)).reverse())
			else reject('未获取到值,请刷新重试')
		})
	})
}

/**
 * 获取字体图标 `document.styleSheets`
 * @method ali 获取阿里字体图标 `<i class="iconfont 图标类名"></i>`
 * @method ele 获取 element plus 自带图标 `<i class="图标类名"></i>`
 * @method ali 获取 fontawesome 的图标 `<i class="fa 图标类名"></i>`
 */
const initIconfont = {
	// iconfont
	ali: () => {
		return getAlicdnIconfont()
	},
	// element plus
	ele: () => {
		return getElementPlusIconfont()
	},
	// fontawesome
	awe: () => {
		return getAwesomeIconfont()
	},
}

// 导出方法
export default initIconfont

awesome.vue,测试页面

<template>
	<div class="awesome-container">
		<el-card shadow="hover" :header="`fontawesome 字体图标(自动载入):${sheetsIconList.length}个`">
			<el-row class="iconfont-row">
				<el-col :xs="12" :sm="8" :md="6" :lg="4" :xl="2" v-for="(v, k) in sheetsIconList" :key="k">
					<div class="iconfont-warp">
						<div class="flex-margin">
							<div class="iconfont-warp-value">
								<i :class="v" class="fa"></i>
							</div>
							<div class="iconfont-warp-label mt10">{{ v }}</div>
						</div>
					</div>
				</el-col>
			</el-row>
		</el-card>
	</div>
</template>

<script lang="ts">
import { toRefs, reactive, onMounted, defineComponent } from 'vue'
import initIconfont from '/@/utils/getStyleSheets'

export default defineComponent({
	name: 'pagesAwesome',
	setup() {
		const state = reactive({
			sheetsIconList: [],
		})
		// 初始化获取 css 样式,这里使用fontawesome的图标(记得加上前缀 `fa`),其它第三方请自行做判断
		const initGetStyleSheets = () => {
			initIconfont.awe().then((res: any) => (state.sheetsIconList = res))
		}
		// 页面加载时
		onMounted(() => {
			initGetStyleSheets()
		})
		return {
			...toRefs(state),
		}
	},
})
</script>```

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值