likes
comments
collection
share

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

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

上面已经介绍为文件资源的加载,并且添加了两个公共组件,所以接下来开始完成组件的自动加载,但是自动加载,改造点太多了,并且组件类型还需要自己添加。其实可以使用自定义脚本指令形式取代,并且还可以对组件类型进行自动补充【自定义脚本指令,然后使用模板生成或修改文件】,这里主要是使用资源加载形式进行处理,后面看有空可以完善一下

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

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】文件夹放公共组件
    • FontIcon: 字体图标组件
    • ImgIcon:图片组件
    • index.ts: 自动加载组件相关逻辑
  • typings: 全局组件没有参数提示,所以需要使用这个来进行添加

思路介绍

  • 规定什么类型文件为需要动态加载的组件【部分可能只是公共组件的一部分内容】
  • 使用资源加载所有globalComponents下规定的组件
  • 使用app.use方式对组件进行注册

思路实现

src\globalComponents\main.ts

import type { App } from "vue";


const getComponents = () => {
    const components = import.meta.glob("./*/index.vue");
    return Object.values(components);
}

const install = (app: App) => {
    const componentList = getComponents();

    componentList.forEach(async (element: any) => {
        const { default: component } = await element();
        console.log(component)
        if (component.name) {
            app.component(component.name, component);
        }
    });
}


export default { install }
  • 通过getComponents获取组件
  • 返回一个带有install属性的对象,当使用app.use时,就会调用该方法,并传入app实例
  • 我们通过install方法进行注册组件

入口文件main.ts


import { createApp } from "vue";
import App from "./App.vue";
import GlobalComponents from "./globalComponents/main";
import "@/assets/iconfont/iconfont.css";



const app = createApp(App);
// 注册全局组件 
app.use(GlobalComponents); 

// 挂载
app.mount("#app");

**问题:**界面上没有展示出来全局组件,并提示没有注册该组件

**猜想:**因为element方法是异步,所以导致组件注册慢于app的挂载,所以在挂载前没有注册成功

**证明猜想:**当你把组件放在v-if内,添加切换操作,就发现组件后面是能正常渲染的

src\App.vue

<script setup lang="ts">
import { ref } from 'vue';


const showIcon = ref(false);

const switchShow = () => {
  showIcon.value = !showIcon.value;
} 

</script>

<template>
  <div>
    <img src="/vite.svg" class="logo" alt="Vite logo" />

    <button @click="switchShow">控制</button>

    <div v-if="showIcon">
      <ImgIcon class="logo vue" icon="vue" folder="logo"></ImgIcon>
      <FontIcon icon="xingbie"></FontIcon>
      <FontIcon icon="bianmindianhua"></FontIcon>
      <ImgIcon folder="logo" icon="index"></ImgIcon>
    </div>

    <img src="./assets/images/logo/vue.svg" class="logo vue" alt="Vue logo" />
  </div>
</template>

解决问题

既然挂载比组件注册快了一点,那么是否可以让挂载等待组件注册后再进行挂载呢?为了这个目的,将改造组件注册,对外提供一个函数,返回一个Promise的插件对象【Promise<{install: (app: App) => void}>

src\globalComponents\index.ts

/** 处理异步问题 */
import { Component, ComputedOptions, MethodOptions, type App } from "vue";

export default async function () {
  const components = import.meta.glob("./*/index.vue");
  const componentList: any = [];
  for (const key in components) {
    const element = components[key];
    const component: any = await element();
    componentList.push(component.default);
  }
  return {
    install: (app: App) => {
      componentList.forEach((element: Component<any, any, any, ComputedOptions, MethodOptions>) => {
        if (element.name) {
          app.component(element.name, element);
        }
      });
    }
  }
}

在导出的函数中先使用async await获取到所有的组件对象,然后通过install方法进行组件注册

修改入口文件main.ts

import { createApp } from "vue";
import App from "./App.vue";
import GlobalComponents from "./globalComponents";
// import GlobalComponents from "./globalComponents/main";
// import "@/assets/iconfont/index.scss";
import "@/assets/iconfont/iconfont.css";


async function init() {
    const app = createApp(App);
    const commonComponents = await GlobalComponents();
    // 注册全局组件 
    app.use(commonComponents); 

    // 挂载
    app.mount("#app");
}

init();

入口文件支持async await,就完成了

添加全局组件参数提示

typings/shims-vue.d.ts

/**
 * 全局组件类型
 */
import FontIcon from "@/globalComponents/FontIcon/index.vue"
import ImgIcon from "@/globalComponents/ImgIcon/index.vue" 


declare module 'vue' {
    interface GlobalComponents {
        FontIcon: typeof FontIcon;
        ImgIcon: typeof ImgIcon;
    } 
}


export { }
  • export { }: 这个是必要的,不然会报错
  • 引入组件,然后拓充 GlobalComponents 接口
  • 该配置文件需要包含在tsconfig.json中的include范围内

最后

到此,自动导入组件就算完成了,后期只需要在globalComponents下新建组件即可自动注册,主要是需要改造的内容有点多,并且也没有办法自动添加组件参数提示。

转载自:https://juejin.cn/post/7258469240734711869
评论
请登录