likes
comments
collection
share

Vue3资源文件加载与自动导入组件【上】

作者站长头像
站长
· 阅读数 45

因为这个内容可能比较多,所以这里分为上下两部分来介绍相关实现,上篇主要讲资源文件加载,后面则利用资源文件加载能力,来实现自动导入公共组件,以及公共组件的参数提示,资源加载能力主要是使用import.meta.glob这个api

这里为完整代码:【非指令版参考项目地址】

Vue3资源文件加载与自动导入组件【下】

目录介绍

|-- 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.tsimageTypes 数组中配置

已使用 globalComponents 注册为全局组件了,所以可以直接使用,而不需要再注册

<template>
  <ImgIcon icon="index" folder="logo"></ImgIcon>
</template>
<script lang="ts" setup></script>
3.调用方法方式获取图片地址

提供了 getIconUrl 方法来访问图片地址,参数同 ImgIcon 组件

getIconUrl("logo", "index");
4.最后

getIconUrlsrc/assets/images/index.ts 中导出 IconImgsrc/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
评论
请登录