在form中使用自定义组件,最终遇到的问题就是,如何让表单拿到自定组件的值,遇到Warning: You cannot set a form field before rendering a field associated with the value.又该如何处理
场景
- antdv的form组件的a-form-item只能绑定一个值,当你一行formitem需要有多个值时,有两种处理方法:
- a-form-item嵌套,就是在这层formitem下再设多个formitem,但是这也会有对齐、lable等问题
- 自定义组件,把自定义组件内的多个值合并为一个给到表单
- 这里使用自定义组件解决该问题,并以行政区域多级选择框组件为例
实现
- 这里具体放出行政区域多级选择框的实现为例,先看组件
<template>
<div class="container">
<a-select
placeholder="请选择省"
show-search
@change="provinceChange"
v-model="provinceCode"
>
<a-select-option :value="province.code" v-for="province of provinceOptions" :key="province.index">{{ province.name }}</a-select-option>
</a-select>
<a-select
placeholder="请选择市"
show-search
@change="cityChange"
v-model="cityCode"
>
<a-select-option :value="city.code" v-for="city of cityOptions" :key="city.index">{{ city.name }}</a-select-option>
</a-select>
<a-select
placeholder="请选择区/县"
show-search
v-model="countyCode"
>
<a-select-option :value="county.code" v-for="county of countyOptions" :key="county.index">{{ county.name }}</a-select-option>
</a-select>
<a-input
placeholder="请输入机构名称"
v-model="detail"
/>
</div>
</template>
<script>
import { cities, cityListfy } from '@/utils/cities.json.js'
export default {
name: 'CitySelector',
data () {
return {
// 下拉框中的v-model绑定的变量需要是undefined才能显示placeholder
provinceCode: undefined,
cityCode: undefined,
countyCode: undefined,
detail: '',
// 省市区下拉框选项, 及当前选择的省和市的children
provinceOptions: [],
nowProChildren: null,
cityOptions: [],
nowCityChildren: null,
countyOptions: []
}
},
computed: {
value: function () { // 组件总的值
return {
provice: this.provinceCode,
city: this.cityCode,
county: this.countyCode,
detail: this.detail
}
}
},
watch: {
value (newVal, oldVal) {
this.$emit('selecChange', newVal)
}
},
mounted () {
this.provinceOptions = cityListfy(cities)
},
methods: {
// 行政区域下拉框的change事件
provinceChange (e) {
// 市和县的下拉框要清空
this.cityCode = undefined
this.countyCode = undefined
this.nowProChildren = cities[e].children
this.cityOptions = cityListfy(this.nowProChildren)
},
cityChange (e) {
// 县的下拉框要清空
this.countyCode = undefined
this.nowCityChildren = this.nowProChildren[e].children
this.countyOptions = cityListfy(this.nowCityChildren)
}
}
}
</script>
- 需要用到的同学,样式自己根据需求调,所以现在组件的值就是value,再watch中,监听到值变化就传递给父组件
- 所以很明显了,父组件里的表单是通过子组件触发事件拿到值的
- 先看html,注册selecChange事件,至于为什么要用
v-decorator="['location']"呢,我们后面再说
<a-form-item label="公司地址" class="li selectli" labelAlign="right">
<cityselector
v-decorator="['location']"
@selecChange="selecChange"
>
</cityselector>
</a-form-item>
- 然后看看selecChange事件,很简单,就是用form.setFieldsValue对表单进行赋值
selecChange (data) {
this.form.setFieldsValue({
location: data
})
}
- 这里就回到刚才的那个问题,为什么要用
v-decorator="['location']",如果不用会发生什么呢?会Warning: You cannot set a form field before rendering a field associated with the value,字面意思,就是在form关联一个value之前,你就给这个field赋值了,发生这种事可能有两种情况
- 一种是在form表单渲染之前就开始赋值了,这种情况就需要注意你赋值的时机,要在表单渲染之后,也可以用
this.$nextTick试试
- 还有一种就是,你还没有关联value,所以不管你在什么时候赋值,都是在关联之前,这种情况就是要用
v-decorator="['location']"的原因,可以看到,我selecChange事件里set的值的属性名就是location,所以这里是关联了的
- 至此,form就拿到自定义组件的值了