Vuex 自动化生成工具

Vuex 自动化生成工具需求文档


1. 需求背景

为提升前端开发效率,减少重复代码编写,需开发一个自动化工具,根据输入参数自动生成完整的 Vuex 存储模块(包括api.js,mutations.js,actions.js,getters.js,mutation-types。js)。
在这里插入图片描述


2. 功能需求
2.1 输入参数
参数名类型必填描述示例值
apiNamestringAPI 名称(驼峰命名)getUserInfo
apiUrlstringAPI 地址/api/user/info
remarkstring接口注释获取用户详细信息
requestTypestringHTTP 方法(默认 GET)post
apiTypestringAPI 分类get create update download

2.2 生成文件及规则
2.2.1 api.js 文件
  • 功能:存储 API 地址常量
  • 生成规则
    /*** 获取用户详细信息*/
    export const getUserInfo = '/api/user/info';
    
  • 校验
    • 文件不存在时自动创建
    • 接口名称或地址重复时抛出错误
2.2.2 mutation-types.js 文件
  • 功能:定义 mutation 类型常量
  • 生成规则
    /*** 获取用户详细信息*/
    export const GETUSERINFO_REQUEST = 'GETUSERINFO_REQUEST';
    export const GETUSERINFO_RECEIVE = 'GETUSERINFO_RECEIVE';
    
2.2.3 mutations.js 文件
  • 功能:生成状态变更逻辑
  • 生成规则
    [type.GETUSERINFO_REQUEST](state) {state.userInfoStatus = 'loading';state.userInfo = {};
    },
    [type.GETUSERINFO_RECEIVE](state, res) {state.userInfoStatus = 'loaded';state.userInfo = res?.content || {};
    }
    
2.2.4 getters.js
  • 功能:生成状态获取方法
  • 生成规则
    export const userInfo = state => state.userInfo || {};
    export const userInfoStatus = state => state.userInfoStatus || '';
    
2.2.5 actions.js
  • 功能:生成 API 调用逻辑
  • 生成规则
    export const getUserInfo = ({ commit }, data) => {commit(type.GETUSERINFO_REQUEST, data);return ajax.post(API.getUserInfo,{ commit },data,type.GETUSERINFO_RECEIVE);
    };
    

3. 非功能性需求
3.1 错误处理
  • 接口名称/地址重复时中止操作并提示
  • 文件权限不足时抛出异常
3.2 目录管理
  • 默认生成到 ./store/modules/ 目录
  • 自动创建缺失的目录层级
3.3 代码风格
  • 统一使用 2 空格缩进
  • 自动生成 JSDoc 注释

4. 使用示例
// 调用示例
addStoreToFile('getUser', '/api/user', '获取用户数据', 'get', 'user');

5. 输出验证

执行成功后需生成以下文件结构:

store/modules/api.jsmutations.jsgetters.jsactions.jsmutation-types.js

基础代码

const fs = require('fs');
const path = require('path');
const BASE_DIR = './store/user'; // 所有文件生成到store/modules下
const apiFilePath = `${BASE_DIR}/api.js`
const mutationsFilePath = `${BASE_DIR}/mutations.js`
const actionsFilePath = `${BASE_DIR}/actions.js`
const mutationTypesFilePath = `${BASE_DIR}/mutation-types.js`
const gettersFilePath = `${BASE_DIR}/getters.js`
// 校验文件内是否已经存在
function _checkCorrect(filePath, regStr, apiUrl) {// 1. 检查文件是否存在if (!fs.existsSync(filePath)) {fs.writeFileSync(filePath, '', 'utf8');}// 2. 读取文件内容const content = fs.readFileSync(filePath, 'utf8');// 3. 检查接口是否已存在const apiRegex = new RegExp(regStr, 'g');if (regStr && apiRegex.test(content)) {throw new Error(`已存在`);return false}// 4. 检查URL是否已存在if (apiUrl && content.includes(apiUrl)) {throw new Error(`接口地址 ${apiUrl} 已存在`);return false}return true
}
// 匹配是否满足条件的函数
function _checkFunctionExists(content, apiName) {// 匹配两种函数定义方式:// 1. export const fnName = ({ commit }) => {...}// 2. export function fnName({ commit }) {...}const funcRegex = new RegExp(`export\\s+(?:const\\s+${apiName}\\s*=\\\s*\\(|function\\s+${apiName}\\s*\\\()`);return funcRegex.test(content);
}
// 重新设置名称
function _getNewApiName(apiName, requestType, apiType) {if (apiType) {// 将apiName首字母大写apiName = apiName.replace(apiName[0], apiName[0].toUpperCase())apiName = requestType == 'get' ? (requestType + apiName) : (apiType + apiName)return apiName}return apiName
}
// 在文件顶部添加创建目录的函数
function _ensureDirectoryExists() {if (!fs.existsSync(BASE_DIR)) {fs.mkdirSync(BASE_DIR, { recursive: true });}
}
// 1. api写入
function addApiToFile(apiName, apiUrl, remark = '', requestType, apiType) {let filePath = `${BASE_DIR}/api.js`let isCorrect = _checkCorrect(apiFilePath, `export const ${apiName} *= *['"].+['"]`, apiUrl)if (isCorrect) {const newApi = `
/*** ${remark} */
export const ${apiName} = '${apiUrl}';\n`;fs.appendFileSync(apiFilePath, newApi, 'utf8');return `接口 ${apiName} 添加成功`;}}
// 2. mutation-types写入
function addMutationTypes(apiName, remark) {apiName = apiName.toUpperCase()let isCorrect1 = _checkCorrect(mutationTypesFilePath, `export const ${apiName + '_REQUEST'} *= *['"].+['"]`)let isCorrect2 = _checkCorrect(mutationTypesFilePath, `export const ${apiName + '_RECEIVE'} *= *['"].+['"]`)if (isCorrect1 && isCorrect2) {let newApi = `
/*** ${remark} */
export const ${apiName + '_REQUEST'} = '${apiName + '_REQUEST'}';\n
export const ${apiName + '_RECEIVE'} = '${apiName + '_RECEIVE'}';\n`;fs.appendFileSync(mutationTypesFilePath, newApi, 'utf8');return `mutation-types ${apiName} 添加成功`;}
}
//3. getters 写入
function addGettersToFile(apiName, remark) {let isCorrect1 = _checkCorrect(gettersFilePath, `export const ${apiName + 'Info'} *= *['"].+['"]`)let isCorrect2 = _checkCorrect(gettersFilePath, `export const ${apiName + 'Status'} *= *['"].+['"]`)if (isCorrect1 && isCorrect2) {let newApi = `
/*** ${remark} */
export const ${apiName + 'Info'} = state =>state[${apiName + 'Info'}]||{};\n
export const ${apiName + 'Status'} = state =>state[${apiName + 'Status'}]||'';\n`;fs.appendFileSync(gettersFilePath, newApi, 'utf8');return `getters ${apiName} 添加成功`;}
}
// 4. mutations 写入
function addMutationsToFile(apiName, remark) {// 1. 初始化文件(如果需要)if (!fs.existsSync(mutationsFilePath)) {fs.writeFileSync(mutationsFilePath, `
import * as type from './mutation-types'
export const state = {}
export const mutations = {}`.trim(), 'utf8');}// 2. 读取最新内容(每次重新读取)let content = fs.readFileSync(mutationsFilePath, 'utf8');// 3. 处理stateconst stateRegex = /export\s+const\s+state\s*=\s*{([^{}]*?(?:\{[^{}]*\}[^{}]*?)*)}/ ///export\s+const\s+state\s*=//\s*{([\s\S]*?)}/;if (stateRegex.test(content)) {content = content.replace(stateRegex, (match, stateContent) => {if (new RegExp(`${apiName}Info\\s*:|${apiName}Status\\s*:`).test(stateContent)) {throw new Error(`State中已存在${apiName}相关属性`);}return `export const state = {${stateContent.trim()}${remark ? `// ${remark}` : ''}${apiName}Info: {},${apiName}Status: '',
}`;});}// 4. 处理mutations(关键修正)const mutationRegex = /export\s+const\s+mutations\s*=\s*{([\s\S]*?)}\s*$/;if (mutationRegex.test(content)) {content = content.replace(mutationRegex, (match, mutationContent) => {if (new RegExp(`\\[type\\.${apiName.toUpperCase()}_(REQUEST|RECEIVE)\\]`).test(mutationContent)) {throw new Error(`Mutations中已存在${apiName}相关操作`);}return `export const mutations = {${mutationContent.trim()}${remark ? `// ${remark}` : ''}[type.${apiName.toUpperCase()}_REQUEST](state) {state.${apiName}Status = 'loading';state.${apiName}Info = {};},[type.${apiName.toUpperCase()}_RECEIVE](state, res) {state.${apiName}Status = 'loaded';state.${apiName}Info = res?.content || {};},
}`;});}// 5. 写入最终结果fs.writeFileSync(mutationsFilePath, content, 'utf8');return `${apiName}相关mutations配置已添加`;
}
//5. actions.js
function addActionsToFile(apiName, remark, requestType) {// 1. 初始化文件(如果需要)if (!fs.existsSync(actionsFilePath)) {fs.writeFileSync(actionsFilePath, `
import * as type from './mutation-types'
import * as API from './api'
import { ajax } from '@/utils/fetch'`.trim(), 'utf8');}// 2. 读取最新内容(每次重新读取)let content = fs.readFileSync(actionsFilePath, 'utf8');// 3. 判断文件中是否存在函数名称为apiName的函数if (_checkFunctionExists(content, apiName)) {throw new Error(`函数 ${apiName} 已存在`);}// 4. 追加新函数const newAction = `
${remark ? `// ${remark}` : ''}  export const ${apiName} = ({ commit }, data) => {commit(type.${apiName.toUpperCase()}_REQUEST, data);return ajax.${requestType}(API.${apiName},{ commit },data,type.${apiName.toUpperCase()}_RECEIVE);};`;fs.appendFileSync(actionsFilePath, newAction, 'utf8');return `${apiName}相关actions配置已添加`;}// apiType:['get', 'create', 'download', 'update', 'delete']
function addStoreToFile(apiName, apiUrl, remark = '', requestType = 'get', apiType) {_ensureDirectoryExists()let newApiName = _getNewApiName(apiName, apiType)// 1. 添加 APIaddApiToFile(newApiName, apiUrl, remark,)// 2. 添加 addMutationTypesaddMutationTypes(apiName, remark)// 3. 添加 gettersaddGettersToFile(apiName, remark)// 4. 添加 mutationsaddMutationsToFile(apiName, remark)// 5. 添加 actionsaddActionsToFile(newApiName, remark, requestType)return 'success'}try {// console.log(addStoreToFile('getName', 'api/user/name', '获取名称'));// console.log(addStoreToFile('getUser', 'api/user/User', '获取用户信息'));console.log(addStoreToFile('getStore1', 'api/user/store1', '获取用户信息', 'post'));} catch (error) {console.error(error.message);
}

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

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

相关文章

深入浅出多路归并:原理、实现与实战案例解析

文章目录 二路归并多路归并方法一:指针遍历(多指针比较法)方法二:小根堆法(最小堆归并) 实际场景外部排序 经典题目丑数Ⅱ方法一:三指针法方法二:优先队列法(K路归并&…

Koji构建系统宏定义注入与Tag体系解析

在Red Hat生态的持续集成链条中,Koji作为核心构建系统,其灵活的宏定义机制与精密的Tag体系是保障软件包高效流转的关键。本文将系统阐述在既有构建目标中注入宏定义的技术路径,并深度解析Koji中Target与Tag的概念架构及其版本演进差异。 一、…

【Kubernetes】架构与原理:核心概念、组件协同及容器化部署解析

文章目录 一、前言二、为什么需要 Kubernetes1. 传统部署方法2. 虚拟化部署3. 容器化部署Ⅰ. 基本概念Ⅱ. 容器编排的必要性Ⅲ. 容器化部署的优势4. k8s 的历史与发展三、Kubernetes 基本概念1. k8s 核心架构解析Ⅰ. 控制平面与工作节点Ⅱ. 各组件协同工作原理2. k8s 核心概念Ⅰ…

Pip Manager本地Python包管理器

在Python开发领域,包管理是每个开发者日常工作中不可或缺的一部分。虽然命令行工具pip功能强大,但对于初学者和非技术背景的用户来说,命令行界面往往显得不够友好。如果使用PyCharm,则可以非常简单的管理安装的Python包&#xff1…

vscode界面设置透明度--插件Glasslt-VSC

【快捷键:透明度提高(CtrAlt Z),透明度降低(CtrAlt C)】

OPENCV形态学基础之一膨胀

一.膨胀的原理 数学表达式:dst(x,y) dilate(src(x,y)) max(x,y)src(xx,yy) 膨胀是图像形态学的基本功能之一,膨胀顾名思义就是求图像的局部最大值操作,它的数学表达式是dst(x,y) dilate(src(x,y)) max(x,y)src(xx,yy)。 从数学的角度来看…

彻底禁用Windows Defender通知和图标

方法 一:通过注册表强制隐藏 Defender 图标(永久生效)​​ (适用于彻底隐藏图标,但需谨慎操作) ​​打开注册表编辑器​​ 按 Win R,输入 regedit 回车。 ​​导航到 Defender 相关注册表项​…

Kafka 2.7.0 单节点安装与启动教程(适配 JDK 1.8)

1. 下载与解压 官方下载 Kafka 2.7.0 https://archive.apache.org/dist/kafka/2.7.0/kafka_2.13-2.7.0.tgz 上传到虚拟机(如 /home/wang/soft/kafka)解压: tar -zxvf kafka_2.13-2.7.0.tgz 2. 配置环境变量(可选,便…

23、Python字符串核心机制解析:驻留原理、对象比较与成员检测实战

适合人群:零基础自学者 | 编程小白快速入门 阅读时长:约5分钟 文章目录 一、问题:Python的字符串驻留机制?1、例子1:字符串驻留现象2、答案:(1)字符串驻留 二、问题:Pyth…

pikachu靶场通关笔记22-2 SQL注入05-2-update注入(报错法)

目录 一、SQL注入 二、update注入 三、报错型注入 四、源码分析 1、代码审计 2、渗透思路 五、渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff…

【prometheus+Grafana篇】基于Prometheus+Grafana实现Redis数据库的监控与可视化

💫《博主主页》: 🔎 CSDN主页 🔎 IF Club社区主页 🔥《擅长领域》:擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(MongoDB)有了…

R语言速释制剂QBD解决方案之四

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》速释制剂混合和润滑工艺研究的R语言解决方案。 原料粒径分布与混合次数对混合均一性的影响 由于acetriptan 的溶解度低,acetriptan 需要粉碎以提高生物利用度。粉碎后的原料…

用python玩转大语言模型——从 RNN 到文本生成大语言模型的奇幻之旅

用python玩转大语言模型——从 RNN 到文本生成大语言模型的奇幻之旅 第一部分:RNN原理及其结构(魔法师的记忆水晶球) 1.1 经典RNN结构(时光旅行者的备忘录) 核心概念 时间循环:RNN通过隐藏状态h在时间步之间传递信息,形成闭环结构参数共享:每个时间步使用相同的权重…

数据结构(9)排序

一、常见排序算法 排序在生活中无处不在,上学这么多年班级排名啥的总有吧,不可能一次都没见过;打游戏有的排行榜不也是有排序的思想在里面,排序倒不是什么特殊的数据结构,但是是非常重要的算法思想,所以在初…

量子计算导论课程设计 之 PennyLane环境搭建

文章目录 具体配置conda 虚拟环境配置Pennylane 正所谓,磨刀不误砍柴工,想要进行量子计算导论的课程设计,首先就是搭建好平台,推荐大家就是本地搭建,那么下面有三种选择 QiskitTensorFlow QuantumPennylane 具体配置…

nginx ./nginx -s reload 不生效

问题 nginx ./nginx -s reload 不生效 解决 不是改opt/nginx下的配置文件是改/usr/local/nginx下的配置文件改之前做好备份

建造者模式深度解析与实战应用

作者简介 我是摘星,一名全栈开发者,专注 Java后端开发、AI工程化 与 云计算架构 领域,擅长Python技术栈。热衷于探索前沿技术,包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践,乐于分享实战经验与…

VScode - 我的常用插件01 - 主题插件Noctis

导言 Noctis 是一款为 Visual Studio Code 提供的主题插件,主打高对比度、护眼、美观。它有多种配色风格,适合不同的开发者审美和工作场景。 一、安装Noctis 二、设置颜色主题 三、测试主题 如上所示,有11种主题背景可以选择。这里&#xff…

【IQA技术专题】图像质量评价IQA技术和应用综述(万字长文!!)

专题介绍 图像质量评价(Image Quality Assessment, IQA)是图像处理、计算机视觉和多媒体通信等领域的关键技术之一。IQA不仅被用于学术研究,更在影像相关行业内实现了完整的商业化应用,涉及影视、智能手机、专业相机、安防监控、…

突然虚拟机磁盘只剩下几十K

第一步:查找哪些文件大于 100M find / -size 100M 第二步:删除掉无用的 log 发现,磁盘剩余空间并没有变大 假如一个文件正在被使用,你删除之后也是不会释放存储空间的。需要关闭相应的服务才能释放。