原因
在业务开发过程中,发现表单有点长,修改一点点,滚动条就不够用,受不了,索性把一个表单直接拆为零散的子表单
图示
在主表单中,在postForm定义表单的所有字段通过v-model分发给子表单,子表单接受,每个子表单定义有validate()方法和getData(), 前者用于验证表单数据,后者用于把数据处理以后返回给主表单
子表单
- 接受postForm, 子表单通过
props接收postForm
props: {
value: Object,
isEdit: {
type: Boolean,
default: false
}
}
- validate方法 验证本身组件的表单项,并返回一个promise对象
// 返回`elementUI`表单验证的结果(为`promise`对象)
validate() {
return this.$refs.goodsInfoFormRef.validate()
}
- getData方法 接受父组件传递进来主表单副本,对副本中的部分字段进行二次处理,返回处理后的主表单副本
getData(postFormCopy) {
// 接收主表单传递的表单副本,进行一系列数据处理
postFormCopy.frequency = parseInt(postFormCopy.frequency)
return postFormCopy
}
主表单
<template>
<div class="app-container">
<el-form ref="postFormRef" :model="postForm" :rules="postFormRules" label-width="120px" label-suffix=":">
<edit-goods-info-detail ref="infoFormRef" v-model="postForm" :is-edit="isEdit" />
<edit-goods-brand-detail ref="brandFormRef" v-model="postForm" :is-edit="isEdit" />
<edit-goods-fav-detail ref="favFormRef" v-model="postForm" :is-edit="isEdit" />
<el-form-item>
<el-button v-loading="loading" type="primary" @click="handleSumbit">提 交</el-button>
<el-button @click="handleCancel">取 消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import EditGoodsInfoDetail from './EditGoodsInfoDetail'
import EditGoodsBrandDetail from './EditGoodsBrandDetail'
import EditGoodsFavDetail from './EditGoodsFavDetail'
// 省略...
export default {
// 省略...
methods: {
handleSumbit() {
Promise.all([
this.$refs.postFormRef.validate(),
this.$refs.infoFormRef.validate(),
this.$refs.brandFormRef.validate(),
this.$refs.favFormRef.validate()
]).then(() => {
// 全部验证通过
const requestApi = this.isEdit ? updateGoods : createGoods
let postFormCopy = _cloneDeep(this.postForm)
postFormCopy = this.$refs.infoFormRef.getData(postFormCopy)
postFormCopy = this.$refs.brandFormRef.getData(postFormCopy)
postFormCopy = this.$refs.favFormRef.getData(postFormCopy)
requestApi(JSON.stringify(postFormCopy))
.then(res => {
this.$message.success(`${this.isEdit ? '编辑成功' : '新增成功'}`)
this.$router.push({ name: 'GoodsList', query: { flush: true }})
})
})
.catch(err => {
console.log(err)
return false
})
}
}
}
</script>
点击提交按钮后,表单会经过如下流程
- 验证主表单和所有子表单的字段,验证失败不提交表单
- 验证通过,复制一份表单,将副本传递给每个子表单,让子表单对数据做最后一次处理
- 处理完数据,发起提交表单的请求
编辑表单
一般流程是
- 获取表单详情
- 获取详情之后,子表单对详情中的数据进行处理,完成页面回显
主表单中
created() {
if (this.isEdit) {
const id = this.$route.query.id
this.postForm.id = id
this.getDetail(this.postForm.id)
.then(() => {
this.$refs.infoFormRef.initEdit()
})
.catch(err => {
console.log(err)
})
}
},
getDetail(id) {
return new Promise((resolve, reject) => {
getGoodsDetail(id).then(res => {
const data = res.data
this.postForm = data
resolve(data)
}).catch(err => {
console.log(err)
reject(err)
})
})
}
子表单
// 省略...
initEdit() {
const detail = this.value
if(detail.gender) {
this.setGender(detail.gender)
this.value.gender = JSON.parse(detail.gender)
}
},
setGender(v) {
let parseRs = JSON.parse(v)
if(Array.isArray(parseRs)) {
if(parseRs.length === 0) {
this.selectedSexLimit = sexLimitStatus.UNLIMI
return
}
if(parseRs.length > 0) {
this.selectedSexLimit = sexLimitStatus.LIMIT
return
}
}
this.selectedSexLimit = ''
return
}
具有关联的子表单
业务需求中,有两个select是强耦合关系,前面select重新选择了,后面的select会被重置,并且发起请求,获取最新的options选项列表,两个select不在一个子表单中,是在两个子表单中。
新增数据
解决方法是,监听前面select的变化,变化的时候,置空后面一个select的已选值,并且发起请求
computed: {
adxId() {
return this.value.adx_id
}
},
watch: {
adxId: {
handler: function(newVal, oldVal) {
this.value.resource_id = ''
// 为空时,不发起请求
if(isEmpty(newVal)) return
this.getResourcesOptions(this.postForm.adx_id)
},
immediate: true
}
}
编辑时
在编辑时候,会涉及重新赋值问题,如果有二次处理,监听到多次变化,导致编辑时,触发监听,把原来的值冲掉情况
所以需要识别出这种场景出来--编辑赋值
- 编辑模式
- 表单的属性值会经历由默认值(一般为空值)变化为有值
watch: {
adxId: {
handler: function(newVal, oldVal) {
const isEmptyToVal = !isEmpty(newVal) && isEmpty(oldVal)
// 编辑状态下,首次服务端赋值时,不进行置空
if(!(this.isEdit && isEmptyToVal)) {
this.value.resource_id = ''
}
if(isEmpty(newVal)) return
this.getResourcesOptions(this.postForm.adx_id)
},
immediate: true
}
}
代码
可以参考git仓库代码