Vue3资源文件加载与自动导入组件【上】
因为这个内容可能比较多,所以这里分为上下两部分来介绍相关实现,上篇主要讲资源文件加载,后面则利用资源文件加载能力,来实现自动导入公共组件,以及公共组件的参数提示,资源加载能力主要是使用import.meta.glob
这个api
这里为完整代码:【非指令版参考项目地址】
目录介绍
|-- auto-register-components
|-- src
| |-- App.vue
| |-- main.ts
| |-- style.css
| |-- vite-env.d.ts
| |-- assets
| | |-- vue.svg
| | |-- iconfont // 字体图标资源
| | | |-- iconfont.css // 普通版本,当前使用的
| | | |-- index.scss // 自定义前缀版本
| | |-- images // 图片资源
| | |-- index.ts
| | |-- icons
| | | |-- language.svg
| | | |-- moon.svg
| | | |-- sun.svg
| | |-- logo
| | |-- index.svg
| |-- constant // 常量文件
| | |-- images.ts
| |-- globalComponents // 需要全局注册的组件
| |-- index.ts // 全局注册的主要文件
| |-- FontIcon // 字体图标组件
| | |-- index.vue
| | |-- README.md
| |-- ImgIcon // 图片组件
| |-- index.vue
| |-- README.md
|-- typings // 其他的ts类型,主要用做全局组件类型提示
|-- shims-vue.d.ts
|-- .gitignore
|-- index.html
|-- package.json
|-- README.md
|-- tsconfig.json
|-- tsconfig.node.json
|-- vite.config.ts
全局组件需要统一注册,所以单独新增【globalComponents】文件夹放公共组件
typings: 全局组件没有参数提示,所以需要使用这个来进行添加
图片资源加载
整体思路:
-
制定规则:
- 范围:托管到的图片资源为
src/assets/images
文件夹内所有相关资源 - 重名规则:出现重名,并标识没有后缀,默认顺序为
@/constant/images
中的imageTypes
决定
- 范围:托管到的图片资源为
-
使用
import.meta.glob
获取指定位置的图片资源 -
将所有文件转为地址存入对象中
-
导出方法获取对象中的地址并返回
-
新建ImgIcon组件在模板中使用
获取指定位置资源
src\assets\images\index.ts
const getIconListMap = () => {
const files = import.meta.glob("./**/*");
const svgs: { [key: string]: { [key: string]: any } } = {};
for (const key in files) {
const iconInfo = key.split("/");
iconInfo.splice(0, 1);
const fileName = iconInfo.pop() || "undefined";
const fileFolder = iconInfo.join("/");
if (!fileFolder) {
continue;
}
if (!svgs[fileFolder]) {
svgs[fileFolder] = {};
}
// https://cn.vitejs.dev/guide/assets.html
svgs[fileFolder][fileName] = new URL(
`./${fileFolder}/${fileName}`,
import.meta.url
).href;
}
return svgs;
};
// 所有的图片资源
const svgs = getIconListMap();
注意点:
这个位置的
new URL
不能直接使用 变量key,而需要手动组装,否则打包后图片资源地址出现问题, 具体可以查看官方文档注意这个文件的位置,文件位置与
import.meta.glob("./**/*")
是相关联的最终
svgs
对象的数据结构大概:{ 文件夹名称:{ 文件名称.后缀:地址 } }
导出获取资源相关内容
src\assets\images\index.ts 添加并导出方法 getIconUrl
/**
* 获取图片地址
* @param folder 文件夹名称
* @param name 图片名称
* @param hasSuffix 是否有后缀
* @returns 图片地址
*/
export const getIconUrl = (folder: string, name: string = "index", hasSuffix: boolean = false) => {
let iconUrl = "";
if (hasSuffix) {
iconUrl = svgs[folder][name];
} else {
imageTypes.some((suffix: string) => {
let iconName = name + suffix;
iconUrl = svgs[folder][iconName];
return iconUrl;
});
}
return iconUrl;
};
- 如果有后缀,就直接获取路径
- 如果没有后缀,则使用
imageTypes
作为后缀排序搜索路径 - 实在没有就直接返回空字符串
这里并没有做容错,因为按道理来说,资源文件应该是存在的,如果没有就应该在开发环境进行提示,但是也可以做容错,然后
console.error
出来
添加组件ImgIcon
<template>
<img :src="showIcon" />
</template>
<script setup lang="ts">
import { getIconUrl } from "@/assets/images";
import { computed } from "vue";
defineOptions({
name: "ImgIcon"
})
const props = defineProps({
folder: {
type: String,
default: "",
},
icon: {
type: String,
default: "index",
},
hasSuffix: {
type: Boolean,
default: false,
}
});
const showIcon = computed(() => {
return getIconUrl(props.folder, props.icon, props.hasSuffix);
});
</script>
- folder:可以设置一个常用的文件夹,减少组件的相关参数
- icon:也可以设置一个默认的文件
- hasSuffix:默认不要后缀,这样更方便。但是也可以默认设置为true,减少查找过程
编写说明文档,完善组件
ImgIcon 使用说明
1. 图片加载
在 src/assets/images
文件夹中找是否有对应的分类,如果没有想要的分类文件夹,那么就手动添加一个文件夹
这个很重要,直接放在
images
文件夹下的图片资源文件是不读取的,加载工作在images/index.ts
文件中完成
2.组件方式使用图片
提供了 ImgIcon
组件 来访问该图片
<template>
<ImgIcon icon="index" folder="logo"></ImgIcon>
</template>
<script lang="ts" setup>
import ImgIcon from "@/globalComponents/ImgIcon/index.vue";
defineComponent({ ImgIcon });
</script>
- folder: 文件夹名称,如果是二级目录中的图片,可以使用
logo/icons
- icon: 图标名称,不带后缀,支持的后缀在
constant\images.ts
的imageTypes
数组中配置
已使用
globalComponents
注册为全局组件了,所以可以直接使用,而不需要再注册
<template>
<ImgIcon icon="index" folder="logo"></ImgIcon>
</template>
<script lang="ts" setup></script>
3.调用方法方式获取图片地址
提供了 getIconUrl 方法来访问图片地址,参数同 ImgIcon 组件
getIconUrl("logo", "index");
4.最后
getIconUrl
在 src/assets/images/index.ts
中导出
IconImg
在 src/globalComponents/IconImg
中
5.svg 下载地址
字体图标资源处理的两种方式
1、字体图标加载
字体图标使用的是阿里的【IconFont字体图标库】, 只需要添加图标到项目,然后下载并替换大部分src/assets/iconfont
中的文件即可
1.1 需要自定义图标前缀可以使用这种模式,一般在组件库中使用,防止图标库冲突使用
- 【IconFont字体图标库】网站中,需要配置
FontClass/Symbol 前缀
, 配置内容与iconfont.scss
的[class^='my-icon-']
的my-icon-
相同, 又与组件FontIcon
的默认前缀相同 - 除
index.scss
外整体替换 index.scss
:- 文件替换方式:将
iconfont.css
除了class
外的所有内容复制过来,到此替换就算完成了 - 链接替换方式:
@import "IconFont网站提供的资源连接";
- 文件替换方式:将
具体可以查看
src\assets\iconfont\index.scss
文件. 因为涉及到组件,并且最终代码以下面的方式为主,所以这里提供一下组件相关代码 FontIcon/index.vue
<template>
<i :class="`my-icon-${icon}`"></i>
</template>
<script setup lang="ts">
defineOptions({ name: "FontIcon" });
defineProps({
icon: { type: String, default: ""},
})
</script>
1.1 普通方式加载图标
直接替换src\assets\iconfont文件
内容,不需要设置前缀,设置了就需要自己在组件中添加
2、组件
编写
这个其实很简单,因为所有的图标都需要一个iconfont样式,所以我们添加一个组件,class
提前添加好iconfont样式
即可
使用
提供了 FontIcon
组件 来访问该字体图标库
<template>
<FontIcon icon="index"></FontIcon>
</template>
<script lang="ts" setup>
import FontIcon from "@/globalComponents/FontIcon/index.vue";
defineComponent({ FontIcon });
</script>
- icon: 图标名称,来自【IconFont字体图标库】
已使用
globalComponents
注册为全局组件了,所以可以直接使用,而不需要再注册
<template>
<FontIcon icon="index"></FontIcon>
</template>
<script lang="ts" setup></script>
最后
到此,资源相关加载基本完成,并且添加了两个组件,这两个组件又是常用组件,所以可以注册为全局组件,下篇开始自动注册这些全局组件
转载自:https://juejin.cn/post/7258483153870209084