element-ui 表单组件的简单封装
背景
在管理系统中我们需要经常使用表单
组件来收集用户的一些数据,如果按照官网的示例一个个表单项去填写不仅代码会变得很长而且麻烦,所以我们有必要去对组件进行再次的封装
需求
需求1:表单项通过配置文件配置
- 表单的类型、key、label、是否必填
示例
MyForm.vue
<template>
<div class="form">
<hr />
<h1>form{{ formData }}</h1>
<el-form ref="formRef" :model="formData" :label-width="labelWidth">
<el-form-item
v-for="(item, index) in formItems"
:key="index"
:label="item.label"
:prop="item.prop"
:rules="item.rules"
>
<template v-if="item.type == 'input'">
<el-input
v-model="formData[item.prop]"
:placeholder="item.placeholder"
></el-input>
</template>
<template v-else-if="item.type == 'select'">
<el-select
v-model="formData[item.prop]"
:placeholder="item.placeholder"
>
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
>
</el-option>
</el-select>
</template>
<template v-else-if="item.type == 'date'">
<el-date-picker
v-model="formData[item.prop]"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd"
>
</el-date-picker>
</template>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: 'MyForm',
// 自定义组件上使用v-model
// 1. 定义model。 2. 需要将model中prop值同时在props中定义
// 父组件通过v-model指令绑定值时会将数据传递给子组件中的modelValue,子组件通过触发"update:modelValue"事件可以通知父组件
model: {
prop: 'modelValue',
event: 'update:modelValue',
},
props: {
modelValue: Object,
formItems: {
type: Array,
required: true,
},
labelWidth: {
type: String,
},
},
data() {
return {
formData: {},
}
},
emits: ['update:modelValue'],
created() {
// 表单初始化
for (let item of this.formItems) {
// 注意:这里要进行响应式的设置,否则表单控件会无法输入的
this.$set(this.formData, item.prop, '')
}
this.$emit('update:modelValue', this.formData)
},
watch: {
formData: {
handler(newValue) {
console.log(newValue)
},
deep: true,
},
},
}
</script>
<style scoped></style>
formConfig.js
const formConfig = {
formItems: [
{
type: 'input',
prop: 'name',
label: '姓名:',
placeholder: '请输入姓名',
rules: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
},
{
type: 'input',
prop: 'age',
label: '年龄:',
placeholder: '请输入年龄',
rules: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
},
{
type: 'select',
prop: 'address',
label: '地址:',
placeholder: '请输入地址',
options: [
{
label: '广州市',
value: 'gz',
},
{
label: '上海市',
value: 'sh',
},
{
label: '深圳市',
value: 'sz',
},
],
},
{
type: 'date',
prop: 'birthday',
label: '生日:',
placeholder: '请输入生日',
},
],
labelWidth: '120px',
}
export default formConfig
Test.vue
<template>
<div>
test:{{ formData }}
<hr />
<my-form v-model="formData" v-bind="formConfig"></my-form>
</div>
</template>
<script>
import MyForm from '@/components/form'
import formConfig from './config/form-config'
export default {
name: 'Test',
components: {
MyForm,
},
data() {
return {
formData: {},
formConfig,
n: 0,
}
},
methods: {
handleUpdate() {
console.log('update')
},
},
}
</script>
<style scoped></style>