有用!京东零售前端小姐姐的提效窍门治好了我的强迫症

前端项目的开发过程中,开发者需要投入大量的时间、精力去进行基础代码的初始化; 在共建项目中,也会出现代码风格不统一的情况,维护成本提高; 前端为了实现UI效果统一,代码复用使用,我们将组件进行原子化、模块化封装,那么在自动化,智能化方向,我们还能做一些什么去实现前端提效呢? 基于简单的配置自动生成可用的业务逻辑代码呢? 在时间/统一性提效层面,总结了下面几种小方法,既能保证风格统一,又能避免"复制粘贴",也能节省共建的小伙伴开发时间。

1、基于vsCode的自定义代码片段snippets

使用频率🌟🌟🌟🌟🌟, 几乎每天都会用到。

•适用场景: 比较适合基础代码的构建,可以是页面,也可以是代码块;可以根据自己的个人使用习惯定义代码片段;

•vscode插件库也提供了vue2,vue3相关snippets插件,可以下载使用

swift 复制代码
{
    "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"
  }
}

根据Snippets语法 编写代码段:

•辑器prefix: 代码片段名字,即输入此名字就可以调用代码片段

•body: 这个是代码段的主体.需要编写的代码放在这里

• <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 : 生成代码后光标的初始位置 , 1: 生成代码后光标的初始位置, </math>1:生成代码后光标的初始位置,2: 生成代码后光标的第二个位置,按 tab 键可进行快速切换,还可以有 <math xmlns="http://www.w3.org/1998/Math/MathML"> 3 , 3, </math>3,4, <math xmlns="http://www.w3.org/1998/Math/MathML"> 5..... 5..... </math>5.....{1,字符}: 生成代码后光标的初始位置(其中 1 表示光标开始的序号,字符表示生成代码后光标会直接选中字符)

•description: 代码段描述,输入名字后编显示的提示信息

•tab键制表符:\t

•换行: \r 或者\n2

2、基于plop插件,实现基础代码的批量生成

使用频率🌟🌟, 初始化新功能代码必用。

官网地址plop秘籍hbs模板语言

适用范围:功能性大模块创建,定义基础页面格式后,支持文件批量创建

plop插件使用

•安装plop插件: npm install ---save-dev plop

•根目录下新建文件plopfile.js

•在项目根目录下创建plop-templates 文件夹,并在plop-templates/view 里新建一个index.hbs/index.vue等模版文件

•最后一步: .gitignore中增加文件, 防止被提交到远程

hbs配置相关:

模板文件中所使用到的参数是由plopfiles.js内的actions数组对象的data传入的;可定义function进行处理后赋值给自定义参数并传入模板中。

•prompts 用户输入:

◦input:输入

◦list:选择,choices数组提供选项

◦confirm:回答y/n

•actions 参数type,有4种:

◦add:根据模板生成文件

◦addMany: 可以看成add的多个版本

◦modify :根据模板修改根据正则替换存在的文件或地方

◦append:将模板或者字符串根据正则添加到符合正则的地方

plopfile.js的基础配置如下,其中plop-templates是自定义业务模版,下面会详细解释;

php 复制代码
// eslint-disable-next-line func-names
module.exports = function (plop) {
  plop.setGenerator('generator', {
      description: '创建列表模板',      // 这里是对这个plop的功能描述
      prompts: [{
        type: 'input', // select
        message: '请输入模块名称如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;
    },
  });
};

**⌛️⌛️⌛️具体使用案例下面会演示哦😊

3、基于json-server,基于简单的字段配置,自动生成增删改查详情5个接口

使用频率**🌟🌟🌟

适用范围: 于前端开发节奏快于后端的情况,可实现接口mock, 减少前端对后端的依赖。当然集团内也有很多mock接口的工具可供使用,这里不做赘述😊;

网站地址接口自动生成器

json-server插件使用

•安装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}](https://link.juejin.cn?target=http%3A%2F%2Flocalhost%3A3000%2Fposts%2F%24%257Bid%257D "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

json 复制代码
{
  "posts": [
    { "id": 1, "title": "json-server", "author": "swj8" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}

**⌛️⌛️⌛️, 再等等,具体使用案例下面会演示哦😊

4、基于页面基础元素封装业务模版

使用频率🌟🌟🌟🌟🌟, 不是在新建,就是在维护的路上;

背景: 目前项目展示数据以表格居多,页面效果相似度较高,考虑将切换逻辑,查询逻辑,页面渲染,接口请求等进行封装。

优势

•开发只需要关注字段的定义接口地址即可,剩下的部分均可实现一键生成。

•跨团队共建中,由于该模型可低成本形成可用页面,开发接受度强,愿意去使用,这样实现了代码风格的统一;

实际使用结果: 穹体、行云测试管理(部分)、数测、物料等多个平台均采用该业务模型完成开发,最大限度上减少了冗余代码的产生;

设计结构图如下, 比较粗糙,关于字段定义渲染页面的配置可以简单看下,业务逻辑相关代码就不做展示了。

css 复制代码
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,
};

5、基于plop,json-server,业务模型,实现10s生成上述页面.

6、基于低代码设计模式,结合后端存储,0代码实现页面搭建;

背景:融合4个物料平台的已有能力,为集团用户提供测试物料生产、查询、配置的统一入口; 对于物料提供方,提供配置化的场景工具构造能力,降低物料工具的维护成本,一直想尝试的低代码平台实现0代码搭建,终于有了机会~

业务场景梳理: 接口配置后,经过参数配置,组件的关联,自动生成页面;

简单流程图可以看下,后期在编排能力上和UI视觉效果上会持续优化。

编排基础页面展示:

除了编排和执行,我们还提供了操作记录查询、工具生成的历史数据查询; 整个的数据结构也都是复用编排的数据结构。

下面基础数据结构,隐藏掉部分关键点,如有兴趣可以去物料平台适用。

json 复制代码
{
    "code": 200,
    "data": {
        "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": "222",
                                                "id": 1
                                            },
                                            {
                                                "defaultValue": "111",
                                                "id": 2
                                            },
                                            {
                                                "defaultValue": "33",
                                                "id": 3
                                            }
                                        ],
                                        "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"
    },
    "message": "查询成功"
}

上述代码配置,只适用于测试物料生成吗? 并非如此,目前物料平台关于按钮级别的操作,后端直接下发工具,前端已经无需参与开发了;后期规划: 后期考虑将前端渲染逻辑进一步封装为插件,类似的功能就可以实现跨平台复用。

7、JoyCode插件使用,支持代码自动补全,图片转代码,需求和任务信息,代码评审等;

链接:JoyCoder插件、JoyCoder-AI助力,快乐编程

Q3发布了VScode版本,对图片上传,代码注释、知识问答、人机对话等功能进行了实践,整体还是非常惊喜,细节探索还在持续,希望工具越来越好~

作者:京东零售平台研发团队 苏文静

来源:京东零售技术 转载请注明来源

相关推荐
吃杠碰小鸡18 分钟前
commitlint校验git提交信息
前端
虾球xz1 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇1 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒1 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员1 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐1 小时前
前端图像处理(一)
前端
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒1 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪2 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背2 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript