如何优雅的处理vue3全局注册(包含全局注册组件类型处理)

起因

之前在我们项目的main.ts中看到了一行这样的代码

ts 复制代码
app.component('svg-icon', SvgIcon)

每每看到他我心里就很痒,思考为什么要把他扔到mian.ts里面。

问题分析

终于在业务不忙的是我决定把它解决掉,我准备参考一下element-puls的方案看看他是如何处理icon并且全局注册的.

看完之后,我准备写一个插件来处理他,让他支持异步的导入全局组件,不说了直接开动。

书写vue插件

我们先来定义一个数据类型用一个数组来存放所有的异步组件,数组元素的类型是对象里面有两个属性是key和component,直接开干

ts 复制代码
//插件部分
import type { App, Component } from 'vue'
type options = {
  key: string
  component: Component
}[]

export default {
  install: (app: App<Element>, options: Readonly<options>) => {
    options.forEach((item) => {
      app.component(item.key, item.component)
    })
  }
}
//数组定义
export const globalComponents = [
  {
    key: 'svg-icon',
    component: () => import('@/components/SvgIcon/index.vue')
  },
  {
    key: 'Modal',
    component: () => import('@/components/Modal/index.vue')
  }
] as const
//main函数调用
import asyncRegisterGlobalComponents from '../plugins/asyncRegisterGlobalComponents'

app.use(asyncRegisterGlobalComponents, globalComponents)

这里书写了一个简单的插件,他的目的就是通过app.component去注册globalComponents中定义的组件,通过() => import('@/components/Modal/index.vue')来让组件实现异步注册。

处理全局组件的类型问题

我们如果在全局注册组件之后,需要把类型定义到global.d.ts中。

ts 复制代码
// global.d.ts
import SvgIcon form '@/components/SvgIcon/index.vue'
declare module 'vue' {
  export interface GlobalComponents {
    SvgIcon:typeof SvgIcon
  }
}

但是在这里我们完全没有必要这么去处理这个类型,我们完全可以通过体操来根据数组自动去生成他的类型。

ts 复制代码
import { ExtendedObjectType } from '@/interface/utilsType'
import { globalComponents } from '@/utils/globalComponents'

type TGlobalComponents<
  T extends typeof globalComponents = typeof globalComponents,
  num extends number[] = [],
  globalObj extends Partial<Record<keyof T[number]['key'], keyof T[number]['component']>> = {}
> = num['length'] extends T['length']
  ? globalObj
  : TGlobalComponents<
      T,
      [...num, 0],
      ExtendedObjectType<
        globalObj,
        Record<
          T[num['length']]['key'],
          Awaited<ReturnType<T[num['length']]['component']>>['default']
        >
      >
    >

declare module 'vue' {
  export interface GlobalComponents extends TGlobalComponents {}
}

这里用到了一个之前写的工具类型ExtendedObjectType,他主要是处理将两个对象联合起来.

ts 复制代码
type _BaseObjType = { [k in PropertyKey]: unknown }

// 用于对象类型合并
export type ExtendedObjectType<obj1 extends _BaseObjType, obj2 extends _BaseObjType> = {
  [k in keyof obj1 | keyof obj2]: k extends Extract<keyof obj1, keyof obj2>
    ? obj1[k] | obj2[k]
    : k extends keyof obj1
    ? obj1[k]
    : obj2[k]
}

结果

废话不多说了直接看看效果,这里没有导入这个组件,他自动识别到了这个组件并且给了类型提示。

相关推荐
爸爸61910 分钟前
07 ArkTS 基础类型与接口定义:从 TypeScript 到鸿蒙的类型升级
javascript·华为·typescript·harmonyos·鸿蒙系统
阿奇__4 小时前
uniapp微信小程序图片上传含回显组件(拍照,相册)
前端·javascript·vue.js
前端甜糖5 小时前
前端如何实现在线预览office常见文件功能?
前端·vue.js
ljs6482739517 小时前
智慧商城(Smart Mall):基于 Spring Boot + Vue 3 的现代化电商平台实战
linux·vue.js·spring boot·后端
析数塔7 小时前
2026前端框架深度解析:React Compiler、Angular Zoneless、Vue 3.5重写游戏规则
前端·vue.js·react.js
paopaokaka_luck18 小时前
英语单词学习系统的设计与实现(基于艾宾浩斯遗忘曲线的智能复习机制、语音朗读、多题型测试与错题自动收录、Echarts图形化分析)
vue.js·spring boot·后端·echarts
Momo__1 天前
Vite 8.1 打包开发模式——10000 组件冷启动 15 倍,"No Bundle Dev" 七年后被自己终结
前端·vue.js·vite
HUMHSX1 天前
Vue 组件通信核心知识点梳理
javascript·vue.js·ecmascript
妙码生花1 天前
从 PHP 到 AI + Golang,程序员自救转型手记(二十六):icon 组件封装
前端·vue.js·typescript
李明卫杭州1 天前
Vue2 & Vue3 中 Router `props` 配置详解:彻底摆脱 `$route` 依赖
前端·vue.js·前端框架