项目地址:git clone form-demo: 封装通用el-form
一个后台管理系统最常见的是表单,表单最常见的是输入框、下拉选择、日期选择、单选、复选框等等, 系统添加若干模块,就复制粘贴若干个el-form、el-form-item,有一说一,完成需求快是快,但是代码冗余的部分太多了,能不能通过配置方式,自动生成el-form、el-form-item
不封装代码前:
封装代码后:
两种封装方式的变量、方法名基本一致!
(1)新建commentForm文件夹,并创建index.vue文件
(2)index.vue中
{{ item.text }}
(3)注意事项:
- el-checkbox中v-model绑定的值要事先存在,不然就会报出无法找到length属性的错误
所以提前在data中声明一个数组,v-model绑定这个数组,返回表单给父组件时,将其添加到表单对象中,重置表单时,使这个数组为空即可实现重置表单功能!
- 重置不成功的原因可能是:(1)未添加prop (2)prop绑定的值与model绑定的对象所对应的属性不一致
重点关注部位:
(1)formItemList中的type决定生成什么类型的表单项,如输入框、下拉选项等等
(2)formItemList中的model表示表单项双向绑定的名称,也是子组件返回对象给父组件中对象的属性名
(3)formItemList中的options表示下拉选项、复选框、单选按钮的选项值
(4)@submitForm绑定的事件可以获取子组件返回给父组件经过校验的表单,通常不在子组件进行网络请求,让父组件进行网络请求
(5)父组件通过$refs获取组件实例从而调用子组件重置表单、提交表单的方法
jsx封装方式借鉴了这篇文章:element-ui 通用表单封装及VUE JSX应用 - 掘金
(1)上篇博客有简单介绍jsx:两种方式对el-table二次封装_码上编程的博客-CSDN博客
(2) 新建jsxForm文件夹,并创建index.js文件
(3)封装代码:
代码逻辑图如下:
export default {
name: 'jsxForm',
props: {
// 生成el-form-item的数组
formItemList: {
type: Array,
default: () => [],
},
// 是否行内表单模式
inline: {
type: Boolean,
default: false,
},
// el-form-item的label宽度
labelWidth: {
type: String,
default: '100px',
},
// 表单校验规则
rules: {
type: Object,
default: () => { },
},
// 按钮列表
buttonList: {
type: Array,
default: () => [],
}
},
data() {
return {
form: {},
checkboxList: []
}
},
methods: {
// 生成选项
generateOption(itemObj) {
let options = []
for (let index = 0; index < itemObj.options.length; index++) {
const item = itemObj.options[index]
switch (itemObj.type) {
// 下拉菜单
case 'select':
options.push( )
break
// 多选框
case 'checkbox':
options.push( )
break
// 单选框
case 'radio':
options.push({item.label} )
break
}
}
return options
},
// 生成下拉菜单
generateSelect(item) {
return {this.generateOption(item)}
},
// 生成多选框
generateCheckbox(item) {
this.form[item.model] = this.checkboxList
return {this.generateOption(item)}
},
// 生成单选
generateRadio(item) {
return
{this.generateOption(item)}
},
// 生成输入框
generateInput(item) {
return (
)
},
// 生成开关
generateSwitch(item) {
return
},
// 生成日期组件
generateDate(item) {
return
},
// 生成表单项
generateFormItems(list = []) {
let formItems = []
list.forEach(item => {
let formItemContent = ''
switch (item.type) {
// 下拉菜单
case 'select':
formItemContent = this.generateSelect(item)
break
// 单选框
case 'radio':
formItemContent = this.generateRadio(item)
break
// 输入框
case 'input':
formItemContent = this.generateInput(item)
break;
// 开关
case 'switch':
formItemContent = this.generateSwitch(item)
break;
// 日期
case 'date-picker':
formItemContent = this.generateDate(item)
break;
// 复选框
case 'checkbox':
formItemContent = this.generateCheckbox(item)
break;
default:
break
}
formItems.push({formItemContent} )
})
return formItems
},
// 按钮列表
generateBtnList() {
let buttons = []
this.buttonList?.forEach(item => {
buttons.push( item.event()}>{item.text} )
})
return buttons
},
// 重置表单
resetForm() {
// 重置复选框
this.checkboxList = []
this.$refs.form.resetFields();
},
// 返回经过校验的表单
returnForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.$emit('submitForm', this.form)
}
})
}
},
render() {
return (
{this.generateFormItems(this.formItemList)}
{this.generateBtnList()}
)
}
}