前端提效小窍门 - 治好了我的强迫症
前端为实现UI效果统一和代码复用使用,在组件原子化、模块化、自动化,智能化方向的探索,实现前端提效。
前端项目的开发过程中,开发者需要投入大量的时间、精力去进行基础代码的初始化; 在共建项目中,也会出现代码风格不统一的情况,维护成本提高; 前端为了实现UI效果统一,代码复用使用,我们将组件进行原子化、模块化封装,那么在自动化,智能化方向,我们还能做一些什么去实现前端提效呢? 基于简单的配置自动生成可用的业务逻辑代码呢? 在时间/统一性提效层面,总结了下面几种小方法,既能保证风格统一,又能避免“复制粘贴”,也能节省共建的小伙伴开发时间。
1、基于vsCode的自定义代码片段snippets,使用频率🌟🌟🌟🌟🌟, 几乎每天都会用到。
适用场景:比较适合基础代码的构建,可以是页面,也可以是代码块;可以根据自己的个人使用习惯定义代码片段;
vscode插件库也提供了vue2,vue3相关snippets插件,可以下载使用
{"Print to console": {"prefix": "list","body": ["<template>"," <div class='box-container'>\n"," </div>","</template>","<script>","export default {"," components: {\n"," },"," mixins: [],"," props: {\n"," },"," watch: {\n"," },"," data() {"," return {\n"," };"," },"," computed: {\n"," },"," created() {\n"," },"," mounted() {\n"," },"," methods: {\n"," },","};","</script>\n","<style scoped lang=\"${1:scss}\">\n","</style>\n",],"description": "Create vue list"}}
辑器prefix: 代码片段名字,即输入此名字就可以调用代码片段 body: 这个是代码段的主体.需要编写的代码放在这里 $1: 生成代码后光标的初始位置, $2: 生成代码后光标的第二个位置,按 tab 键可进行快速切换,还可以有 $3,$4,$5..... ${1,字符}: 生成代码后光标的初始位置(其中 1 表示光标开始的序号,字符表示生成代码后光标会直接选中字符) description: 代码段描述,输入名字后编显示的提示信息 tab键制表符:\t 换行: \r 或者\n2
2、基于plop插件,实现基础代码的批量生成,使用频率🌟🌟, 初始化新功能代码必用。
安装plop插件:npm install -–save-dev plop 根目录下新建文件plopfile.js 在项目根目录下创建plop-templates 文件夹,并在plop-templates/view 里新建一个index.hbs/index.vue等模版文件 最后一步:.gitignore中增加文件, 防止被提交到远程
prompts 用户输入:
input:输入 list:选择,choices数组提供选项 confirm:回答y/n
actions 参数type,有4种:
add:根据模板生成文件 addMany:可以看成add的多个版本 modify :根据模板修改根据正则替换存在的文件或地方 append:将模板或者字符串根据正则添加到符合正则的地方
// eslint-disable-next-line func-namesmodule.exports = function (plop) {plop.setGenerator('generator', {description: '创建列表模板', // 这里是对这个plop的功能描述prompts: [{type: 'input', // selectmessage: '请输入模块名称如system(可省略)',name: 'modeName',default: '',}, {type: 'input',name: 'apiName',message: '接口和存储的名称',},{type: 'confirm',name: 'hasCreate',message: '是否需要创建页面',default: this.hasCreate,}],actions: (data) => {const { hasCreate } = data;const routePath = "{{modeName}}";console.log(hasCreate, 'dsdsdsdsd');const actions = [{type: 'add',path: 'src/pages/{{modeName}}/list.vue',templateFile: 'plop-templates/list/list.hbs', // 模板文件}, {type: 'add',path: 'src/pages/{{modeName}}/components/config.js', // 文件存放路径templateFile: 'plop-templates/list/components/config.js', // 模板文件}, {type: 'add',path: 'src/pages/{{modeName}}/components/mixins.vue', // 文件存放路径templateFile: 'plop-templates/list/components/mixins.js', // api}, {// 配置路由文件type: 'modify',path: 'src/router/index.js',pattern: /\/\/ generator import/,template: "import {{modeName}} from './modules/{{modeName}}';\n// generator import", //增加标记,下次填充的时候匹配到这个关键字部分}, {// 配置路由文件type: 'modify',path: 'src/router/index.js',pattern: /\/\/ generator router/,template: `{\n...{{modeName}},\n},\n// generator router`,}, {type: 'add',path: 'src/router/modules/{{apiName}}.js', // 文件存放路径templateFile: 'plop-templates/list/route.js', // api}, {type: 'add',path: 'src/api/{{apiName}}.js', // 文件存放路径templateFile: 'plop-templates/api/demo.js', // 文件夹下的modules.ts}, {type: 'add',path: 'src/store/modules/{{apiName}}/index.js', // 文件存放路径templateFile: 'plop-templates/store/index.js', // 文件夹下的modules.ts}, {type: 'add',path: 'src/store/modules/{{apiName}}/db.json', // 文件存放路径templateFile: 'plop-templates/store/db.json', // 文件夹下的modules.ts}];if (hasCreate) {actions.push({type: 'add',path: 'src/pages/{{modeName}}/create.vue', // 文件存放路径templateFile: 'plop-templates/list/create.vue', // 模板文件});}return actions;},});};
安装json-server插件:npm install -g json-server 创建db.json文件,在文件中写入想要构造的接口 运行json-server --watch db.json
注意是在同db.json目录下哦 支持修改port, json-server --watch db.json --port 8887
获取全部数据:【GET】http://localhost:3000/posts
用_gte,_lte来设置一个字段的取值范围。包含开头和结尾:http://localhost:3000/posts?id_gte=1&id_lte=12; 用_ne来设置不包含某个值:http://localhost:3000/articles?id_ne=1&id_ne=2 _start来指定开始位置,_end来指定结束位置,或者是用_limit来指定从开始位置起往后取几个数据。不包含_start,包含_end:http://localhost:3000/articles?_start=2&_end=5 用_like来设置模糊匹配某个字段:http://localhost:3000/articles?id_like=3 用q来设置全文搜索:http://localhost:3000/articles?q=maxime 分页采用 _page 来设置页码, _limit 来控制每页显示条数。如果没有指定 _limit ,默认每页10条:http://localhost:3000/articles?_page=2&_limit=3 _sort指定要排序的字段,_order指定正序还是逆序(asc | desc ,默认是asc):http://localhost:3000/articles?_sort=id&_order=desc
获取数据详情:【GET】http://localhost:3000/posts/${id} 或者http://localhost:3000/posts?id=${id}&name=${name} 添加数据:【POST】http://localhost:3000/posts 更新数据:【PUT】http://localhost:3000/posts 删除数据:【DELETE】http://localhost:3000/posts
{"posts": [{ "id": 1, "title": "json-server", "author": "swj8" }],"comments": [{ "id": 1, "body": "some comment", "postId": 1 }],"profile": { "name": "typicode" }}
开发只需要关注字段的定义和接口地址即可,剩下的部分均可实现一键生成。 跨团队共建中,由于该模型可低成本形成可用页面,开发接受度强,愿意去使用,这样实现了代码风格的统一; 实际使用结果:穹体、行云测试管理(部分)、数测、物料等多个平台均采用该业务模型完成开发,最大限度上减少了冗余代码的产生;
设计结构图如下, 比较粗糙,关于字段定义渲染页面的配置可以简单看下,业务逻辑相关代码就不做展示了。
import {formatArrayToObj} from '@/utils/index.js';const permissionOptions = [{label: '公有', value: 'PUBLIC', default: '', type: 'primary'},{label: '私有', value: 'PRIVATE', default: '', type: 'warning'},];const permissionOptionsObj = formatArrayToObj(permissionOptions, 'value');const searchFormJson = {title: '列表的查询条件',tabs: [{label: '我创建的', value: 'creator'}, {label: '全部', value: 'all'}],elements: {name: {label: '数据名称',component: 'el-input',default: '',attrs: {style: {width: '200px',},},},auth: {label: '权限范围',component: 'pul-select',default: '',attrs: {options: permissionOptions,style: {width: '200px',},},},creator: {label: '创建人',component: 'pul-erp',default: {},hidden: true,attrs: {placeholder: '请精确搜索创建人',style: {width: '200px',},},},},formAttrs: {labelWidth: '90px',labelWidthBorder: false,inline: true,class: 'fold-form-item',},feature: {hasSearchBtn: true,},};const createDataForm = {title: '创建数据',elements: {name: {label: '数据名称',// required: true,component: 'el-input',default: '',rule: [{ required: true, message: '请输入数据名称', trigger: 'change' }],attrs: {placeholder: '请输入英文、数字、下划线',maxlength: "30",'show-word-limit': true,},},desc: {label: '数据描述',component: 'el-input',default: '',attrs: {type: "textarea",autosize: { minRows: 2, maxRows: 4},},},auth: {label: '权限范围',labelDesc: '若生效范围为私有,则仅用户自己可以查看使用;若生效范围为公有,则其他用户也可查看和引用',component: 'pul-select',required: true,default: 'PUBLIC',attrs: {options: permissionOptions,style: {display: 'inline-block',width: '100%',},},},},formAttrs: {labelWidth: '120px',labelWidthBorder: false,inline: true,'label-position': 'right',class: 'fold-form-item',},feature: {hasSearchBtn: false,},};export {permissionOptionsObj,searchFormJson,createDataForm,};
编排基础页面展示:
除了编排和执行,我们还提供了操作记录查询、工具生成的历史数据查询;整个的数据结构也都是复用编排的数据结构。
{"activeTabId": 0, //展开即可定位到当前激活的tab"description": "注册京东账号","environment": "test","tabInfos": [{"allBlocks": [{"blockId": 1226,"blockModules": [{"chosenTemplateId": 0,"interfaceId": 0,"modules": [{"approveConfig": null,"associateInfo": null, //接口信息"paramConfig": {"max": 0,"min": 0,...组件参数配置},"paramInfos": [],"required": false,"stepValue": "","styleProperties": { //组件样式信息"background": "#fef0f0","customRow": 4},"tabId": 115,"templateIds": [],"toolId": 11,"type": 7,"typeName": "使用说明","updateTime": 1698924413000}],"styleProperties": null,"templateSelectId": 0,"templateSelectName": "","templateSelects": [ //支持模版绑定切换组件{"moduleIds": [{"defaultValue": "test0001pin","id": 1230},{"defaultValue": "18801333","id": 1877},{"defaultValue": "test0001pin","id": 1232}],"templateId": 44,"templateName": "普通账号"}]}],"category": "desc","styleProperties": {"formLabelWidth": "auto","formCompWidth": "auto","formItemWidth": "100%"}},],"createTime": 1698924413000,"description": "","groupId": 16,"groupName": "xx","id": 115,"modifier": null,"name": "xx","sequence": 1,"status": 3,"statusName": "成功","toolId": 11,"updateTime": 1698924413000}],"toolId": 11,"toolName": "xx"}
上述代码配置,只适用于测试物料生成吗?并非如此,目前物料平台关于按钮级别的操作,后端直接下发工具,前端已经无需参与开发了;后期规划:后期考虑将前端渲染逻辑进一步封装为插件,类似的功能就可以实现跨平台复用。