一、存在及需要解决的问题
一般在做后台OA的时候会发现表单重复代码比较多,且逻辑基本一样,每次新加一个表单都需要拷贝基本一致的代码结构,然后只是简单地修改对应的字段进行开发
二、预期结果
提取重复的表单逻辑形成通用的组件,通过约定的JSON数据结构配置生成表单
1、使用方法
"formOption" :is-reset-form-flag="isResetFormFlag">
复制代码
接收的props:
isResetFormFlag:是否更新表单内容标志,用于触发更新表单的formModel
formOption:表单配置,下有详细配置说明
isDisabled:表单是否可编辑
2、单一表单组配置
{
name: 'channel-form',
data: {},
items: [
{
label: '类型',
name: 'biz_type',
type: 'select',
dataList: [{
index: 1,
text: '业务部'
}]
}
],
rules: {
name: [{ required: true, message: '请输入产品名称', trigger: 'blur' }]
},
btnList: [{
text: '保存',
type: 'primary',
onClick: this.commitForm
}]
}
复制代码
3、多表单组配置
formOption: {
name: 'channel-form',
data: {},
groups: [{
title: '',// 组标题
tips: ''// 组提示
items: [] // 组表单项,和单一组配置一致
}]
}
复制代码
三、实现逻辑
根据配置输出不同的form-item,需要特殊处理的表单项通过jsx
由使用的地方自定义实现
什么是JSX:cn.vuejs.org/v2/guide/re…
文档:egoist.moe/2017/09/21/…
使用JSX原因:表单包含了大部分的选项,但是也有很多不确定的情况需要依赖外部自己实现,相对于template的方式jsx使用起来更加灵活
四、配置文档
节点 | 描述 | 类型 | 是否必须 | 备注 |
---|---|---|---|---|
name | 表单名 | String | 否 | 默认名 oa-form |
data | 表单数据 | Object | 否 | 用于编辑场景异步请求的表单填充数据 |
groups | 表单组 | Array | 否 | groups 和 items 不应该同时存在,groups 中包含了items,如果groups为空取外部的items渲染,groups不为空仅渲染groups组内容 |
items | 表单项 | Array | 否 | 支持的type类型:输入框:input、textarea;多选框:checkbox;单选框:radio;下拉菜单:select |
rules | 表单校验规则 | Object | 否 | 节点名需要与items配置的name一一对应 |
btnList | 按钮列表 | Array | 否 | 会在回调函数包含表单的数据及表单引用 |
六、VUE JSX 遇到的一些问题
v-model支持: babel-plugin-jsx-v-model
sync 修饰符写法
visible={ this.dialogImgVisible } {...{on: {'update:visible': (val) => { this.dialogImgVisible = val }}}}
复制代码
七、部分实现代码
1、生成列表
generateList (itemObj) {
let itemEle = []
for (let index = 0; index < itemObj.dataList.length; index++) {
const item = itemObj.dataList[index]
switch (itemObj.type) {
// 下拉菜单
case 'select':
itemEle.push( )
break
// 多选框
case 'checkbox':
itemEle.push({ item.text } )
break
// 单选框
case 'radio':
itemEle.push({ item.text } )
break
}
}
return itemEle
}
复制代码
2、生成下拉菜单
generateSelect (item) {
return { this.generateList(item) }
}
复制代码
备注:其他项实现类似
3、render函数
render (h) {
let ele = []
// 表单内容
if (this.isGroup) {
ele = this.generateGroup()
} else {
ele = this.generateFormItems(this.formOption.items)
}
// 按钮列表
let btnListEle = []
this.formOption.btnList.forEach((btn) => {
btnListEle.push(type={ btn.type } on-click={ () => { btn.onClick(this.$refs[this.formName], this.formModel) } }>{ btn.text } )
})
return (
"oa-form-container">
'150px'}>
{ ele }
'0' : '150px'}>{ btnListEle }
)
}
复制代码
八、最后贴一个表格的封装
复制代码
1、使用方法
"columns" :table-data="tableData" :loading="loading" @sort-change="sortChange">
复制代码
2、columns 配置
{
label: '',
prop: '',
width: '100',
sortable: true
render: ()=>{}
}
复制代码
自定义配置渲染,传入render函数,如果有render函数,优先使用render函数结果
Github地址:github.com/mrtanweijie…