antdv中form表单中使用自定义组件的总结

场景

  • 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就拿到自定义组件的值了
posted @ 2022-07-01 10:00  Mizuki-Vone  阅读(2189)  评论(0)    收藏  举报