vue3+vite插件开发

插件开发目的:由于我司使用的前端技术栈为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.tsconst 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 } = configconst 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: [//...otherPluginswatchFolderPlugin({fileName: pathResolve('src/api/Api.d.ts'),folderName: pathResolve('src/api/module'),}),],// ...otherConfig})

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CS.AI】GPT-4o:重新定义人工智能的新标杆

文章目录 1 序言2 GPT-4o的技术亮点3 GPT-4o与前代版本的对比3.1 热门AI模型对比表格GPT-3.5GPT-4GPT-4oBERTT5 3.2 其他 4 个人体验与感受5 结论 1 序言 嘿,大家好!今天要聊聊一个超级酷的AI新突破——GPT-4o!最近,OpenAI发布了…

MTK联发科MT6897(天玑8300)5G智能移动处理器规格参数

天玑 8300 采用台积电第二代 4nm 制程,基于 Armv9 CPU 架构,八核 CPU 包含 4 个 Cortex-A715 性能核心和 4 个 Cortex-A510 能效核心,CPU 峰值性能较上一代提升 20%,功耗节省 30%。 此外,天玑 8300 搭载 6 核 GPU Mal…

kafka-重试和死信主题(SpringBoot整合Kafka)

文章目录 1、重试和死信主题2、死信队列3、代码演示3.1、appication.yml3.2、引入spring-kafka依赖3.3、创建SpringBoot启动类3.4、创建生产者发送消息3.5、创建消费者消费消息 1、重试和死信主题 kafka默认支持重试和死信主题 重试主题:当消费者消费消息异常时&…

android中调用onnxruntime框架

创建空白项目 安装Android Studio及创建空白项目参考:【安卓Java原生开发学习记录】一、安卓开发环境的搭建与HelloWorld(详细图文解释)_安卓原生开发-CSDN博客 切记:build configuration language 一定选择Groovy!官…

Java——IO流(一)-(1/8):File、IO流概述、File文件对象的创建(介绍、实例演示)

目录 File IO流概述 File文件对象的创建 介绍 实例演示 File 存储数据的方案 变量 double money 9999.5 数组 int[] age new int[100];对象 Student s new Student()集合 List<Student> students new ArrayList<>()…

Chrome 源码阅读:跟踪一个鼠标事件的流程

我们通过在关键节点打断点的方式&#xff0c;去分析一个鼠标事件的流程。 我们知道chromium是多进程模型&#xff0c;那么&#xff0c;我们可以推测&#xff1a;一个鼠标消息先从主进程产生&#xff0c;再通过跨进程通信发送给渲染进程&#xff0c;渲染进程再发送给WebFrame&a…

L45---506.相对名次(java)--排序

1.题目描述 2.知识点 &#xff08;1&#xff09;String.join(" ", words) 是 Java 中的一个语法&#xff0c;用于将数组或集合中的元素连接成一个单独的字符串&#xff0c;连接时使用指定的分隔符。这里的 " " 是作为分隔符使用的一个空格字符串。 Strin…

4、后端本地环境搭建

后端本地环境搭建 4.1 安装jdk 下载完成后双击安装的 jdk &#xff0c;点下一步&#xff0c;选择安装目录&#xff0c;一直点下一步&#xff0c;直到结束。 安装完成后同样需要配置环境变量 window s 搜索查看高级系统设置—— 高级 —— 环境变量 —— 系统变量 1、新建一…

API接口测试工具:jmeter的安装、汉化、Jmeter桌面快捷图标和基本使用

文章目录 测试工具&#xff1a;JmeterJmeter安装和配置Jmeter汉化设置中文语言&#xff1a;永久方式设置中文语言&#xff1a;临时方式 设置Jmeter桌面快捷图标jmeter基本用法Jmeter无法保存测试问题解决 测试工具&#xff1a;Jmeter Jmeter依赖于JDK&#xff0c;所以必须确保…

第十一届蓝桥杯C++青少年组中/高级组国赛2020年10月真题解析

一、单选题 第1题 在数组中&#xff0c;数组名表示&#xff08; &#xff09;. A:数组第1个元素的首地址 B:数组第2个元素的首地址 C:数组所有元素的首地址&#xff0c; D:数组最后1个元素的首地址 答案&#xff1a;A 数组名是一个地址&#xff0c;指向第一个元素 第2题 …

中继器、集线器、网桥、交换机、路由器和网关

目录 前言一、中继器、集线器1.1 中继器1.2 集线器 二、网桥、交换机2.1 网桥2.1.1 认识网桥2.1.2 网桥的工作原理2.1.3 生成树网桥 2.2 交换机2.2.1 交换机的特征2.2.2 交换机的交换模式2.2.3 交换机的功能 三、路由器、网关3.1 路由器的介绍3.2 路由器的工作过程3.2.1 前置知…

多客圈子论坛系统 httpGet 任意文件读取漏洞复现

0x01 产品简介 多客圈子论坛系统是一种面向特定人群或特定话题的社交网络&#xff0c;它提供了用户之间交流、分享、讨论的平台。在这个系统中&#xff0c;用户可以创建、加入不同的圈子&#xff0c;圈子可以是基于兴趣、地域、职业等不同主题的。用户可以在圈子中发帖、评论、…

17- Redis 中的 quicklist 数据结构

在 Redis 3.0 之前&#xff0c;List 对象的底层数据结构是双向链表或者压缩列表&#xff0c;然后在 Redis 3.2 的时候&#xff0c;List 对象的底层改由 quicklist 数据结构实现。 其实 quicklist 就是【双向链表 压缩列表】组合&#xff0c;因为一个 quicklist 就是一个链表&…

【产品研发】NPDP价值作用概述

导读&#xff1a;本文结合个人实践和思考对NPDP的价值和作用做了概述说明&#xff0c;对于产品经理而言掌握NPDP的知识体系并且应用到实际工作中&#xff0c;这是非常有必要的。走出以往狭隘的产品研发工作认知&#xff0c;以开放心态学习国际化产品创新开发流程将极大提升产品…

深度学习的舌象诊断:从舌头上了解系统性疾病!

首先 深度学习算法能否解决东方医学中依靠医生经验的诊断问题&#xff1f;而要实现这个目标&#xff0c;需要什么呢&#xff1f; 用舌头诊断被称为口腔健康的指标&#xff0c;但在东方医学中&#xff0c;舌头也被用来评估全身的状况。换句话说&#xff0c;通过分析舌头的图像…

Java学习-JDBC(一)

JDBC 概念 JDBC(Java Database Connectivity)Java数据库连接JDBC提供了一组独立于任何数据库管理系统的APIJava提供接口规范&#xff0c;由各个数据库厂商提供接口的实现&#xff0c;厂商提供的实现类封装成jar文件&#xff0c;也就是我们俗称的数据库驱动jar包JDBC充分体现了…

C#上位机开发

目录 一、上位机简介二、C#语法三、新建VS工程四、WinForm控件4.1 属性4.2 事件4.3 窗体方法4.4 常用控件4.5 布局 五、Serial上位机5.1 UI界面设计5.2 功能设计 六、项目打包成安装包6.1 前提准备6.2 打包步骤 一、上位机简介 在单片机项目开发中&#xff0c;上位机也是一个很…

SwiftUI六组合复杂用户界面

代码下载 应用的首页是一个纵向滚动的地标类别列表&#xff0c;每一个类别内部是一个横向滑动列表。随后将构建应用的页面导航&#xff0c;这个过程中可以学习到如果组合各种视图&#xff0c;并让它们适配不同的设备尺寸和设备方向。 下载起步项目并跟着本篇教程一步步实践&a…

【C语言训练题库】扫雷->简单小游戏!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 题目 2. 解析 3. 代码 4. 小结 1. 题目 小sun上课的时候非常喜欢玩扫雷。他现小sun有一个初始的雷矩阵&#xff0c;他希望你帮他生成一个扫雷矩阵。 扫雷…

Vue3_对接腾讯云COS_大文件分片上传和下载

目录 一、腾讯云后台配置 二、安装SDK 1.script 引入方式 2.webpack 引入方式 三、文件上传 1.new COS 实例 2.上传文件 四、文件下载 腾讯云官方文档&#xff1a; 腾讯云官方文档https://cloud.tencent.com/document/product/436/11459 一、腾讯云后台配置 1.登录 对…