vue3+vite插件开发

news2024/11/20 10:21:37

插件开发目的:由于我司使用的前端技术栈为vue3+ts+vite2.X+axios,在前端代码框架设计初期,做了把axios挂载到proxy对象上的操作,具体可见我的另一篇文章vue3+TS自动化封装全局api_ts 封装+腾讯位置api-CSDN博客

现在可以实现vue2的类似this.$api.xxx去调用接口,但是vue2源码使用的是flow来实现,并且搭配typeScript不太友好(由于装饰器语法过于复杂,这里不讨论vue2+装饰器来使用typeScript),故vue2项目没有开发webpack插件去实现代码补全

这篇文章主要介绍的是vue3+ts+vite来开发时的代码补全情况

在使用vue/react+ts开发时,我们把api挂载到全局后,例如封装好axios后需要按模块划分请求,此时会创建一个modules文件夹,里面存放各个模块的请求,当把module所有的文件都动态挂载到proxy实例上时,我们可以通过proxy.$api.文件名.请求名去发起请求

例如:proxy.$api.test_api.test()

1.把modules下所有的api挂载到proxy对象上

这里以vite2和vite4.X举例

// vite 2.X
// src/api/index.ts
// 动态加载module下所有的文件
const files = import.meta.globEager('./module/*.ts')
const models= {}
for (const key in files) {
  const keys = {}


  for (const v in files[key]) {
    Object.assign(keys, { [v]: files[key][v] })
  }
    
  models[key.replace(/(\.\/module\/|\.ts)/g, '')] = keys
}
export default models
// vite4.X以上版本
// src/api/index.ts

const models = {}

const modules = import.meta.glob('./module/*.ts')
const moduleEntries = Object.entries(module)

for (const [key, apiFetchFn] of moduleEntries) {
  try {
    const module = await apiFetchFn()
    const keys = Object.fromEntries(Object.entries(module))
    models[key.replace(/(\.\/module\/|\.ts)/g, '')] = keys
  } catch (error) {
    console.error('API挂载初始化异常:', error)
  }
}

export default models
// src/main.ts
import { createApp } from 'vue'
import api from '@/api'
const app = createApp(App)
app.config.globalProperties.$api = api
//src/xxx.vue
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()!

async function foo(){
    const res = await proxy.$api.test_api.testFetch()
}

2.为proxy使用$api添加类型提示

第一点我们已经完成把所有的请求挂载proxy上并且可以通过proxy.$api.xxx.xxx去发起请求,为proxy添加拥有$api的类型很简单,只需要在xxx.d.ts文件声明@vue/runtime-core添加类型即可

//src/global.d.ts
declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $api: any
  }
}

以上我们为proxy添加了$api属性,值为any,所以我们在使用proxy是会出现$api的代码提示,如下图

3.为$api添加代码提示

众所周知,在vue+ts开发的项目中,只要全局声明了XXX.d.ts文件,并且在里面使用declare声明的类型可以在全局访问到,那么我们思路可以放在声明一个xxx.d.ts文件,该文件的key可以取api/module下面的所有文件名,值直接使用typeScript的typeof import该文件即可获取到

3.1在api文件下新建Api.d.ts文件,里面声明所需要的文件类型,如下

        这里假使module文件夹已有test_api文件

declare namespace GlobalApi {
  interface Api {
    test_api: typeof import('@/api/module/test_api')
  }
}

3.2使用$api时出现代码提示

4.如何自动生成Api.d.ts文件内容呢

我想大家第一反应肯定是写脚本去处理,当module文件下的文件变动时,重新执行脚本即可,那么如何监听到module文件夹下文件的改动呢?但是我不想手动执行脚本怎么处理,这里我们可以使用nodejs的fs模块

4.1在根目录声明一个ts文件,起名为generateApi.ts(随意)

import fs from 'fs'
import type { Plugin } from 'vite'

/**
 * @type 插件配置项
 */
interface IPluginConfig {
  /**生成的.d.ts文件名 */
  fileName: string
  /**查找的文件夹名 */
  folderName: string
}

/**
 * @method 更新Api.d.ts内容
 * @description 生成Api类型后挂载到proxy上获取proxy?.$api.xxx代码提示
 */
function updateApiDeclaration(config: IPluginConfig) {
  const { fileName, folderName } = config
  const moduleFiles = fs.readdirSync(folderName)
  const apiContent = generateApiDeclaration(moduleFiles)
  fs.writeFileSync(fileName, apiContent)
}

/**
 * @method 根据api/module文件名生成Api.d.ts内容
 * @param {string[]}  moduleFiles 文件名
 */
function generateApiDeclaration(moduleFiles: string[]) {
  const interfaceEntries = moduleFiles.map((filename) => `  ${filename.replace('.ts', '')}: typeof import('@/api/module/${filename.replace('.ts', '')}')`).join('\n  ')
  return `declare namespace GlobalApi {
  interface Api {
  ${interfaceEntries}
  }
}
`
}

/**
 * @method 使用fs观察module文件夹变动
 * @description 观察到文件夹内的文件变动后重新生成Api.d.ts文件
 */
export default function watchFolderChange(pluginConfig: IPluginConfig): Plugin {
  return {
    name: 'watch-folder-plugin',
    config(config, { mode }) {
      if (mode === 'development') {
        fs.watch(pluginConfig.folderName, (eventType) => {
          if (['change', 'rename'].includes(eventType)) {
            updateApiDeclaration(pluginConfig)
          }
        })
      }
    },
  }
}

4.2 在vite.config.ts里引入

import watchFolderPlugin from './generateApi'

export default defineConfig({
  plugins: [
     //...otherPlugins
     watchFolderPlugin({
       fileName: pathResolve('src/api/Api.d.ts'),
       folderName: pathResolve('src/api/module'),
     }),

  ],
    // ...otherConfig


})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1798793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Visual C++ Redistributable下载

安装程序的时候提示丢失mfc140u.dll 如下图,查了资料说可以下载Visual C Redistributable来进行处理 下载Visual C Redistributable 1.打开网站 https://www.microsoft.com/zh-cn/download/details.aspx?id48145&751be11f-ede8-5a0c-058c-2ee190a24fa6True) 2.点击下载 …

Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明

Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明 目录 Python 机器学习 基础 之 处理文本数据 【处理文本数据/用字符串表示数据类型/将文本数据表示为词袋】的简单说明 一、简单介绍 二、处理文本数据 三、用…

linux 服务器上离线安装 node nvm

因为是离线环境 如果你是可以访问外网的 下面内容仅供参考 也可以继续按步骤来 node 安装路径 Node.js — Download Node.js nvm 安装路径 Tags nvm-sh/nvm GitHub 后来发现 nvm安装后 nvm use 版本号 报错 让我去nvm install 版本 我是内网环境 install不了 下面 你要 把安…

K210视觉识别模块学习笔记4: (MaixHub)训练与使用自己的模型_识别字母

今日开始学习K210视觉识别模块: 模型训练与使用_识别字母 亚博智能的K210视觉识别模块...... 固件库: maixpy_v0.6.2_52_gb1a1c5c5d_minimum_with_ide_support.bin 文章提供测试代码讲解、完整代码贴出、测试效果图、测试工程下载 这里也算是正式开始进入到视觉识别的领域了…

问题:1、彩色餐巾可以渲染就餐气氛,下列说法错误的是 #知识分享#其他

问题:1、彩色餐巾可以渲染就餐气氛,下列说法错误的是 A.如艳红、大红餐巾给人以庄重热烈的感觉; B.橘黄、鹅黄色餐巾给人以高贵典雅的感觉; C.湖蓝色在夏天能给人以凉爽、舒适之感&#xff1…

python脚本打包为exe并在服务器上设置定时执行

python脚本打包为exe并在服务器上设置定时执行 1. Python脚本打包2. 将打包好的Python脚本放入服务器3. 在服务器上设置其定时执行 1. Python脚本打包 首先,下载pyinstaller 键盘winR打开终端,输入命令:pip install pyinstaller,…

AI大模型,普通人如何抓到红利?AI+产品经理还有哪些机会

前言 随着人工智能技术的飞速发展,AI大模型正逐渐渗透到我们的工作和生活中,为普通人带来了前所未有的便利和机遇。然而,如何有效地抓住这些红利,让AI大模型为我们所用,成为了许多人关注的焦点。 对于普通人而言&…

GIGE 协议摘录 —— 引导寄存器(四)

系列文章目录 GIGE 学习笔记 GIGE 协议摘录 —— 设备发现(一) GIGE 协议摘录 —— GVCP 协议(二) GIGE 协议摘录 —— GVSP 协议(三) GIGE 协议摘录 —— 引导寄存器(四) GIGE 协议…

计算机视觉与模式识别实验2-2 SIFT特征提取与匹配

文章目录 🧡🧡实验流程🧡🧡SIFT算法原理总结:实现SIFT特征检测和匹配通过RANSAC 实现图片拼接更换其他图片再次测试效果(依次进行SIFT特征提取、RANSAC 拼接) 🧡🧡全部代…

基于Texture2D 实现Unity 截屏功能

实现 截屏 Texture2D texture new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); texture.Apply(); 存储 byte[] array ImageConversion.EncodeToPNG(texture); if (!…

MATLAB format

在MATLAB中,format 是一个函数,用于控制命令窗口中数值的显示格式。这个函数可以设置数值的精度、显示的位数等。以下是一些常用的 format 命令: format long:以默认的长格式显示数值,通常显示15位有效数字。format s…

揭秘!如何从精益生产转向智能制造

企业在“工业4.0、智能制造、互联网”等概念满天飞的环境下迷失了方向,不知该如何下手,盲目跟风。 君不见,很多企业在“工业4.0、智能制造、互联网”等概念满天飞的环境下迷失了方向,不知该如何下手,盲目跟风&#xf…

完美落地的自动化测试框架(pytest):智能生成?业务依赖?动态替换?报告构建?你来,这儿有!

前言 随着软件测试行业的快速发展,去测试化、全员测开化的趋势,技术测试已成为确保软件质量不可或缺的一环。 但对于许多没有代码基础或缺乏系统性自动化知识的测试人员来说,如何入手并实现高质量的自动化测试成为了一个挑战。 为此&#xff…

怎么将3d的模型同比例缩放?---模大狮模型网

在展览3d模型设计过程中,经常需要对3d模型进行缩放以满足不同的需求。然而,有时候缩放操作可能会导致模型失去比例,造成不必要的麻烦。模大狮将介绍如何将展览3D模型按比例缩放,帮助展览设计师们更好地掌握这一关键的模型设计技巧…

Ubuntu 安装好虚拟环境后,找不到workon 命令

1、安装虚拟环境 pip3 install virtualenv pip3 install virtualenvwrapper 2、安装完成后 workon 命令。 找不到workon 命令 执行,source virtualenvwrapper.sh 执行后,在使用workon命令,即可完成。

HQL面试题练习 —— 求连续段的最后一个数及每个连续段的个数

目录 1 题目2 建表语句3 题解 题目来源:拼多多。 1 题目 有一张表t_id记录了id,id不重复,但是会存在间断,求出连续段的最后一个数及每个连续段的个数。 ----- | id | ----- | 1 | | 2 | | 3 | | 5 | | 6 | | 8 | | …

Unity基础实践小项目

项目流程: 需求分析 开始界面 选择角色面板 排行榜面板 设置面板 游戏面板 确定退出面板 死亡面板 UML类图 准备工作 1.导入资源 2.创建需要的文件夹 3.创建好面板基类 开始场景 开始界面 1.拼面板 2.写脚本 注意事项:注意先设置NGUI的分辨率大小&…

FactoryTalk View Site Edition的VBA基本应用

第一节 在VBA中标签的读取和写入 本例要达到的目标是通过FactoryTalk View Site Edition(以下简称SE)的VBA来访问PLC中的下位标签,并实现标签的读写。 1.准备工作 打开SE,选择应用程序类型(本例是Site Edition Netwo…

【qt】MDI多文档界面开发

MDI多文档界面开发 一.应用场景二.界面设计三.界面类设计四.实现功能1.新建文档2.打开文件3.关闭所有4.编辑功能5.MDI页模式6.瀑布展开模式7.平铺模式 五.总结 一.应用场景 类似于vs的界面功能,工具栏的功能可以对每个文档使用! 二.界面设计 老规矩,边做项目边学! 目标图: 需…

[职场] 美术指导的重要作用 #学习方法#笔记

美术指导的重要作用 美术指导是广告、电影、电视剧等创意作品中的一个重要角色,负责整体视觉风格和美术设计的指导和管理。 美术指导的目标是通过视觉表达来传达故事的情感、氛围和主题,以及塑造角色和场景的形象。 美术指导在创作过程中扮演着重要的角…