# 表单模版
二次封装
json格式开发提高开发效率
# 详情
# :form-attr 表单属性
formAttr: { title: '用户管理', size: 'small' }
# :item-attr 项属性
itemAttr: [
{ label: '工号:', type: 'input', key: 'no', maxlength: 30 },
{ label: '姓名:', type: 'input', key: 'name', maxlength: 50 },
{ label: '手机号:', type: 'input', key: 'phone', maxlength: 50 },
{ label: '邮箱:', type: 'input', key: 'email', maxlength: 50 },
{ label: '用户类型:', type: 'select', key: 'userType' },
{ label: '账号状态:', type: 'radio', key: 'status' },
{
label: '业务警种:',
type: 'checkbox',
key: 'policeCategory',
width: '98%',
multiple: true
},
{ label: '入职日期:', type: 'daterange', key: 'inDate' },
{ label: '在职状态:', type: 'radio', key: 'jobStatus' },
{ label: '离职日期:', type: 'daterange', key: 'outDate', disabled: true }
]
# :rules 表单校验属性
自定义校验:
- 手机号、邮箱 等
- 1.先声明一个匿名函数
- 2.把函数名赋值给
validator
即可
const checkPhone = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入手机号'))
} else if (!regPhone.test(value)) {
callback(new Error('手机格式错误'))
} else {
callback()
}
}
rules: {
no: [{ required: true, message: '请输入工号', trigger: 'blur' }],
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
phone: [{ required: true, trigger: 'blur', validator: checkPhone }],
email: [{ trigger: 'blur', validator: checkEmail }],
userType: [{ required: true, message: '请选择用户类型', trigger: 'blur' }],
jobStatus: [{ required: true, message: '请选择在职状态', trigger: 'blur' }],
inDate: [{ required: true, message: '请选择入职日期', trigger: 'blur' }],
policeCategory: [{ required: true, message: '请选择业务警种', trigger: 'blur' }],
status: [{ required: true, message: '请选择账号是否启用', trigger: 'blur' }]
}
提示:
多选类型 types 和默认值 def-value 可以动态获取
# :types 多选赋值属性
types: {
userType: [
{ value: '01', label: '普通客服' },
{ value: '02', label: '部门负责人' },
{ value: '03', label: '管理员' }
],
policeCategory: [
{ value: '01', label: '交管' },
{ value: '02', label: '户政(治安)' },
{ value: '03', label: '出入境' },
{ value: '04', label: '监所' },
{ value: '05', label: '技防' },
{ value: '06', label: '法制' }
],
status: [{ value: '01', label: '启用' }, { value: '02', label: '停用' }],
jobStatus: [{ value: '01', label: '在职' }, { value: '02', label: '离职' }]
}
# :def-value 默认值属性
defValue: { status: '01', jobStatus: '01' }
提示:
formCompEl
是表单的锚点 ref="formCompEl"
# submitForm() 提交方法
/** return Promise() */
this.$refs['formCompEl']
.submitForm()
.then(formData => {
console.log(formData)
})
# resetForm() 重置表单方法
this.$refs['formCompEl'].resetForm()
# @change(formData) 多选手动改变值事件
# 交互按钮
提示:
表单最后提供了一个 slot
<MyForm
ref="formCompEl"
:form-attr="formAttr"
:item-attr="itemAttr"
:rules="rules"
:types="types"
:def-value="defValue"
@change="onchange">
<el-form-item>
<el-button type="primary" @click="submitForm">保存</el-button>
<el-button type="info" @click="resetForm">重置</el-button>
</el-form-item>
</MyForm>
# 组件源码
温馨提示
复制在自己的components公共文件下即可
知道了<template>
<div class="form-components">
<div v-if="formAttr.title" style="display: flex;">
<el-divider
content-position="left"
class="title"
>
{{ formAttr.title }}
</el-divider>
</div>
<el-form
ref="formEl"
:rules="rules"
:model="form"
:size="formAttr.size ? formAttr.size : 'small'"
:label-width="formAttr.lableWidth ? formAttr.lableWidth : '150px'"
>
<template v-for="(item, index) in itemAttr">
<div
:key="index"
class="box-item"
:style="'width:' + (item.width ? item.width : '49%')"
>
<el-form-item :prop="item.key" :label="item.label">
<!-- 输入框 -->
<div v-if="item.type === 'input'" :style="'width:' + item.inputWidth">
<el-input
v-model="form[item.key]"
clearable
:disabled="item.disabled"
:maxlength="item.maxlength"
:placeholder="item.placeholder"
/>
</div>
<!-- 多行文本框 -->
<div
v-else-if="item.type === 'textarea'"
:style="'width:' + item.inputWidth"
>
<el-input
v-model="form[item.key]"
type="textarea"
clearable
:rows="item.rows"
:maxlength="item.maxlength"
:placeholder="item.placeholder"
/>
</div>
<!-- 单选框 -->
<div
v-else-if="item.type === 'radio'"
:style="'width:' + item.inputWidth"
>
<el-radio-group
v-if="types[item.key]"
v-model="form[item.key]"
@change="onchange"
>
<el-radio
v-for="(type, indexRadio) in types[item.key]"
:key="indexRadio"
:label="type.value"
>{{ type.label }}</el-radio>
</el-radio-group>
</div>
<!-- 复选框 -->
<div
v-else-if="item.type === 'checkbox'"
:style="'width:' + item.inputWidth"
>
<el-checkbox-group v-if="types[item.key]" v-model="form[item.key]">
<el-checkbox
v-for="(type, indexCbox) in types[item.key]"
:key="indexCbox"
:label="type.value"
>{{ type.label }}</el-checkbox>
</el-checkbox-group>
</div>
<!-- 下拉框 -->
<div
v-else-if="item.type === 'select'"
:style="'width:' + item.inputWidth"
>
<el-select
v-model="form[item.key]"
:multiple="item.multiple"
:placeholder="item.placeholder"
clearable
style="width: 100%;"
>
<el-option
v-for="(select, selectKey) in types[item.key]"
:key="selectKey"
:label="select.label"
:value="select.value"
/>
</el-select>
</div>
<!-- 日期选择 -->
<div v-else :style="'width:' + item.inputWidth">
<el-date-picker
v-model="form[item.key]"
:type="item.type"
:placeholder="item.placeholder"
:disabled="item.disabled"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间"
clearable
style="width: 100%;"
:value-format="(item.valueFormat ? item.valueFormat : 'timestamp')"
/>
</div>
</el-form-item>
</div>
</template>
<slot />
</el-form>
</div>
</template>
<script>
export default {
name: 'FormTempComponents',
props: {
formAttr: { type: Object, default: ()=> { title: '' } },
itemAttr: { type: Array, default: ()=> [] },
rules: { type: Object, default: ()=> {} },
types: { type: Object, default: ()=> {} },
defValue: { type: Object, default: ()=> {} }
},
data() {
return {
form: {}
}
},
watch: {
defValue(v) {
Object.keys(v).forEach(key => {
this.$set(this.form, key, v[key])
})
}
},
created() {
this.itemAttr.forEach(elem => {
if (elem.type === 'checkbox') {
this.$set(this.form, elem.key, [])
}
})
},
mounted() {
if (JSON.stringify(this.defValue) !== '{}') {
Object.keys(this.defValue).forEach(key => {
this.$set(this.form, key, this.defValue[key])
})
}
},
methods: {
onchange() {
const newObj = JSON.parse(JSON.stringify(this.form))
this.$emit('change', newObj)
},
submitForm() {
const newFormObj = JSON.parse(JSON.stringify(this.form))
const isValidate = JSON.stringify(this.rules)
return new Promise((resolve, reject) => {
if (isValidate !== '{}') {
this.$refs['formEl'].validate((valid) => {
if (valid) {
resolve(newFormObj)
} else {
reject()
}
})
} else {
resolve(newFormObj)
}
})
},
resetForm() {
// TODO
Object.keys(this.form).forEach(key => {
this.$set(this.form, key, null)
})
this.$emit('onreset')
}
}
}
</script>
<style scoped>
.form-components >>> .el-divider__text {
font-size: 18px;
}
.form-components .box-item {
display: inline-block;
}
</style>