背景
公司项目前后端分离后, 后台管理系统的前端部分用 element ui 重构了一波.
我们发现, 后台管理系统的前端功能比较类似, 在不同业务模块中, 基本上都有数据列表的增删改查.
管理后台业务页面. PNG
如上图, 每个业务模块的入口列表都大同小异, 需要搜索栏, 表格, 分页器, 操作按钮, API 请求, 子页面跳转等功能.
组件化可以提高代码的复用, 如搜索栏, 我们根据业务场景需求, 将常用的 input,select,time Picker 等常用表单组件封装到 SearchBar.vue 里, 通过传入配置参数调用.
- <search-bar
- :search-btn-param="searchBtnParam"
- :search-input-param="searchInputParam"
- @goSearch="setSearchParam"
- @reset="resetSearchBar"
- />
- data() {
- return {
- searchInputParam: [
- {
- label: '搜索 2',
- type: 'datePickerRange',
- width: '280px',
- feedbackName: 'loanTime',
- },
- {
- label: '搜索 5',// 标签
- type: 'input',// 组件类型
- width: '140px',// 组件宽度
- feedbackName: 'title',//emit 时, 回传到调用页面的当前数据的字段名
- placeholder:' '
- }
- ],
- searchBtnParam: [
- {
- label: '查找',
- type: 'primary',// 可选择值 primary success info warning danger
- emitName: 'goSearch'//emit 派发的事件名称
- }
- ]
- },
但页面却不能使用组件的方式复用代码, 开发人员需要手动 copy 类似页面作为基础开始开发.
这样做存在以下问题:
冗余代码多: copy 的页面引入了大量当前业务用不上的依赖与交互逻辑, 需开发人员检查删减.
命名不规范: func, 注释, class,name 等若未根据当前业务作修改, 导致语义不明, 后期维护困难.
关联文件修改繁琐: 新增页面后, 需要修改路由文件等配置信息. 人工操作容易发生漏改, 出现 bug 却不知所以.
基于对以上问题的考虑, 我们希望通过脚本, 自动化页面初始化生成过程.
解决方法
利用 node 操作读写文件, 正则表达式匹配修改文件内容
以我司后台管理系统的列表页面自动化生成为例, 讲述实现的步骤
1. 编写模板页面 example.vue.
将搜索栏, 列表表格, 分页器, 数据操作按钮, 确认弹框等常用模块引, 需要使用正则匹配修改的地方做好注释.
2. 编写自动生成页面脚本 generatePage.JS
- // 根目录下, terminal 输入 node ./src/components/page/generatePage/generatePage.JS componentName=hello folderName=hello
- // 生成列表页面模板文件 componentName 为文件名称, folderName 为文件夹名称, 等号两边不能空格
- const fs = require('fs')
- const path = require('path')
- let componentName = 'newComponent'
- let folderName = 'folderName'
- // 复制一份 example.vue 到 page 文件夹的 folderName 文件夹下, 重命名为 componentName
- function copyExample() {
- // 读取模板文件 example.vue
- fs.readFile('./src/components/page/example/Example.vue', encoding = 'utf8',
- function(err, data) {
- if (err) {
- throw err
- } else {
- // 读取成功后, 判断生成路径的文件夹是否存在
- fs.readdir(`./src/components/page/${folderName}`, (err, folder) => {
- if (err) {// 无此文件夹, 则生成该文件夹, 再生成 component.vue
- fs.mkdir(`./src/components/page/${folderName}`, {recursive: false},
- (err) => {
- if (err) throw err
- else {
- console.log(` 无 ${folderName} 文件夹 `)
- fs.writeFile(
- `./src/components/page/${folderName}/${componentName}.vue`,
- data, encoding = 'utf8', function(error) {
- if (error) {
- throw error
- } else {
- console.log(`----------- 已生成 ${componentName}.vue 组件文件 -----------`)
- }
- })
- }
- })
- } else {// 有此文件夹, 则直接生成 component.vue
- console.log(` 有 ${folderName} 文件夹 `)
- fs.writeFile(
- `./src/components/page/${folderName}/${componentName}.vue`, data,
- encoding = 'utf8', function(error) {
- if (error) {
- throw error
- } else {
- console.log(`----------- 已生成 ${componentName}.vue 组件文件 -----------`)
- }
- })
- }
- })
- }
- })
- }
- // 修改 util.JS 的路由生成函数
- function fixedFormatRoutes() {
- fs.readFile('./src/util/util.js', encoding = 'utf8', function(err, data) {
- if (err) {
- throw err
- } else {
- const reg1 = componentName.slice(0, 3)
- const insertPoint = /\/\/new route insert here/// 查找插入点
- const insertCode = 'else if (component.startsWith(\''+reg1+'\')) {\n' +
- 'require([\'../components/page/'+folderName+'/\'+ component + \'.vue\'], resolve)\n' +
- '} //new route insert here'// 插入到文件中的代码
- if (!data.match(reg1)) {// 已有对应路由生成代码, 则跳出, 否则改写 formatRoutes 函数代码
- let newData = data.replace(insertPoint,insertCode)
- fs.writeFile('./src/util/util.js', newData, encoding = 'utf8', function(error) {
- if (error) {
- throw error
- } else {
- console.log('------------ 已改写 util.js 路由生成函数代码 -------------')
- }
- })
- } else {
- console.log(`-----------formatRoutes 已存在 ${reg1} 的路由生成代码 --------------`)
- }
- }
- })
- }
- copyExample()
- fixedFormatRoutes()
3. 执行脚本生成模板
node ./src/components/page/generatePage/generatePage.JS componentName=hello folderName=hello
执行脚本生成页面. gif
至此, 顺利生成页面!
还有一个例子
笔者用 KOA 写服务器端接口时, controller,router,App.JS 需要同步修改, 现在使用脚本, 每次只需配置一个 mock 数据的 JSON 文件, 即可初始相关接口文件.
接口配置文件. PNG
自动化生成脚本. PNG
总结
上述自动生成页面方式有如下优点:
模板页面精简, 通用, 无冗余逻辑, 交互代码.
关联文件, 名称命名通过 node 的读写操作自动修改, 无需开发人员人工干预
比手动 copy 快, 出错少
谢谢阅读~~~~~~~
来源: http://www.jianshu.com/p/a77d77d12315