根据数据自动生成表单
我们只需要给组件传递一个数组formDataArr,
这个数组formDataArr中包含key,label 显示的值,type 组件类型,
keyName绑定的key名,defaultValue 绑定keyName的默认值,
placeholder 提示语等
在组件中,我们会遍历传递过来的数组formDataArr,
使用<el-row> 组件作为行,<el-col>作为列(子项)
为啥要使用这2个组件,因为后面我们需要实现响应式
根据type类型,根绝v-if生成我们需要的组件。
<el-form>组件中的 model 我们会在formDataArr拿到它里面的keyName,
然后组成一下新的对象。
<template>
<div class="art-page">
<fromChild :formDataArr="formDataArr"></fromChild>
</div>
</template>
<script>
import fromChild from '@/components/fromChild'
export default {
components:{
fromChild
},
data() {
return {
/**
* id 必须值,
* label 显示的值
* type 组件类型
* keyName 绑定的key
* defaultValue 绑定的key的默认值
* placeholder 提示语
* */
formDataArr: [
{
key: '1',
label: '姓名',
type: 'el-input',
keyName: 'name',
defaultValue: '李四',
placeholder: '用户大老爷请输入',
},
{
key: '2',
label: '爱好',
type: 'el-select',
defaultValue: '01',// 回填的值
placeholder: '用户大老爷请选择',
keyName:'className',
options: [
{ value: '01', label: '旅游' },
{ value: '02', label: '打游戏' },
{ value: '03', label: '写代码' }
]
},
{
key: '3',
label: '经历',
type: 'el-date-picker',
placeholder: '请选择',
keyName:'experienceTime',
}
],
}
}
}
</script>
<template>
<div>
<el-form ref="form" :model="exposeOutFormData" label-width="80px">
<el-row :gutter="20" class="set-el-row">
<el-col :span="8" v-for="item in formDataArr" :key="item.id">
<!-- 输入框 -->
<el-form-item :label="item.label" v-if="item.type==='el-input'">
<el-input v-model="exposeOutFormData[item.keyName]"></el-input>
</el-form-item>
<!-- 下拉框 -->
<el-form-item :label="item.label" v-if="item.type==='el-select'">
<el-select v-model="exposeOutFormData[item.keyName]" :placeholder="item.placeholder">
<el-option :label="itemOption.label" :value="itemOption.value" v-for="(itemOption,itemIndex) in item.options" :key="itemIndex"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="item.label" v-if="item.type==='el-date-picker'">
<el-date-picker
v-model="exposeOutFormData[item.keyName]"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
export default {
props:{
// 传递过来的值
formDataArr:{
type:Array,
default:()=>{
return []
}
}
},
data() {
return {
exposeOutFormData:{}
}
},
created(){
let obj ={}
// 会遍历传递过来的数组formDataArr,拿到它里面的keyName生成一个新对象,作为model的值
this.exposeOutFormData = this.formDataArr.forEach(element => {
if(element.keyName){
obj[element.keyName] = element.defaultValue
}
})
this.exposeOutFormData = obj
}
}
</script>
<style lang="scss" scoped>
.set-el-row{
margin-left: 0px !important;
margin-right: 0px !important;
}
</style>
响应式布局
由于用户的设备分辨率不同,
我们需要你动态去设置每一行的显示列。
这个时候我们可以借助 element-ui中的下面几个属性
xs <768px
sm ≥768px
md ≥992px
lg ≥1200px
xl ≥1920px
<el-form ref="form" :model="exposeOutFormData" label-width="80px">
<el-row :gutter="32" class="set-el-row">
<el-col :xl="6" :lg="8" :md="12" :sm="12" :xs="24" v-for="item in formDataArr" :key="item.id">
<!-- 其他代码不动 -->
/el-col>
</el-row>
</el-form>
设备分辨率 ≥1920px 一行显示4列
设备分辨率 ≥1200px 一行显示3列
设备分辨率 ≥992px 一行显示2列
设备分辨率 ≥768px 一行显示2列
设备分辨率 <768px 一行显示2列
规则校验
现在我们想实现表单的校验。
我们需要给组件传递一个ruleObj对象,
这个对象包含的验证规则,触发方式,是否是必须验证。
子组件会接收这对象中的属性。
下面来实现一个<el-input>不能够为空的校验规则。
<el-date-picker> 选择的日期不能超过当前日期。
子组件绑定验证相关属性
<el-form ref="form" :model="exposeOutFormData" label-width="80px">
<el-row :gutter="32" class="set-el-row">
<el-col :span="6" v-for="item in formDataArr" :key="item.id">
<!-- 输入框的规则 -->
<el-form-item :prop="item.keyName" :rules="{
required:item.ruleObj && item.ruleObj.required,
trigger: item.ruleObj && item.ruleObj.trigger,
validator: item.ruleObj && item.ruleObj.validatorHandler
}"
:label="item.label" v-if="item.type==='el-input'">
<el-input v-model="exposeOutFormData[item.keyName]"></el-input>
</el-form-item>
</el-col>
<!-- 日期的 -->
<el-form-item :prop="item.keyName" :rules="{
required:item.ruleObj && item.ruleObj.required,
trigger: item.ruleObj && item.ruleObj.trigger,
validator: item.ruleObj && item.ruleObj.validatorHandler
}"
:label="item.label" v-if="item.type==='el-date-picker'">
<el-date-picker
v-model="exposeOutFormData[item.keyName]"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
</el-row>
</el-form>
父组件的规则验证
formDataArr: [
{
key: '1',
label: '姓名',
type: 'el-input',
keyName: 'name',
defaultValue: '李四',
placeholder: '用户大老爷请输入',
ruleObj:{
required: true,
trigger: 'blur',
validatorHandler(rule, value, callback) {
if (!value) {
return callback(new Error('高贵的用户,姓名不能够为空'))
}
callback()
}
}
},
{
key: '3',
label: '经历',
type: 'el-date-picker',
placeholder: '请选择',
keyName:'experienceTime',
ruleObj:{
required: true,
trigger: 'blur',
validatorHandler(rule, value, callback) {
if (value &&value.length) {
let entTime = value[1].getTime()
let nowTime = new Date().getTime()
console.log(entTime, nowTime)
if(entTime>nowTime){
return callback(new Error('高贵的用户,选择的时间不能大于当前时间'))
}else{
callback()
}
}else{
return callback(new Error('高贵的用户,请选择时间'))
}
}
}
},
]
获取表单数据
我们在子组件中提供获取表单数据的按钮。
通过 this.$emit 向外暴露方法和数据。
在点击按钮之前,如果有规则则会校验。
可以通过 this.$refs.form.validate这个方法来进行验证。
下面我们就来简单实现一下
子组件提供获取数据的方法
<el-form ref="form" :model="exposeOutFormData" label-width="80px">
<!-- -->
.....这里是组件相关的代码,保持不变...
<!-- -->
<el-row :gutter="32" class="set-el-row">
<el-col :xl="6" :lg="8" :md="12" :sm="12" :xs="24" >
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
methods:{
submitForm(){
// 进行规则相关的验证
this.$refs.form.validate((valid) => {
if (valid) {
// 向父组件暴露方法和提供数据
this.$emit('submitForm', this.exposeOutFormData)
} else {
return false;
}
});
}
}
父组件得到表单相关数据
<fromChild ref="fromChild" :formDataArr="formDataArr" @submitForm="submitForm"></fromChild>
methods: {
submitForm(formData){
console.log('表单中的值', formData)
}
}