AntD of Vue 中 <AForm> 表单域组件化使用的尝试

最近有一个项目,我发现有一些表单内容高度重复的情况,几张页面的表单虽有些细微差,但还是有很多同样的表单内容,或者 表单域A表单域B 同时出现在一个页面中的这种情况。

我就想着能不能把他们都提出来,单独的做成组件在再使用到这些内容的时直接引入对应的表单域组件,并且可以把下拉菜单的远程查询也放到组件中,这样就会精简点很多重复的代码。


说做就做嘛,先简单把一个弹出框组件内的表单内容提取出来,然后再引入这个表单域组件。
(因为Vue我没做高亮,所以就暂且用HTML的高亮替代了)

<template>
  <div>
    <a-form-item label="客户姓名">
      <a-input placeholder="请输入客户姓名" v-decorator="['name', validatorRules.name]" />
    </a-form-item>
    <a-form-item label="性别">
      <a-radio-group v-decorator="['gender', validatorRules.gender]">
        <a-radio-button :value="1"></a-radio-button>
        <a-radio-button :value="0"></a-radio-button>
      </a-radio-group>
    </a-form-item>
    <a-form-item label="联系电话">
      <a-input placeholder="请输入客户联系电话" v-decorator="['phone', validatorRules.phone]" />
    </a-form-item>
    <a-form-item label="备注信息">
      <a-input placeholder="请输入备注信息" v-decorator="['remark', validatorRules.remark]" />
    </a-form-item>
  </div>
</template>
<script>
export default {
  name:"MemberForm",
  data(){
    return {
      validatorRules: {
        name: {
          rules: [{ required: true, whitespace: true, message: '请填写客户姓名' }]
        },
        gender: { rules: [], initialValue: 1 },
        phone: {
          rules: [
            { required: true, whitespace: true, message: '请填写客户联系电话' },
            { pattern: /^((0\d{2,3}-\d{7,8})|(1\d{10}))$/, message: '请输入正确联系电话! 例:010-8888888/13888888888' }
          ]
        },
        remark: {
          rules: [{ max: 120, message:'备注信息最多为120字' }]
        },
      }
    }
  },
}
</script>
<template>
  <a-modal
    title="客户信息"
    :width="600"
    :visible="visible"
    :confirmLoading="confirmLoading"
    cancelText="关闭"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-form :form="form" :labelCol="labelCol" :wrapperCol="wrapperCol">
        <MemberFormBase />
      </a-form>
    </a-spin>
  </-modal>
</template>
<script>
import pick from 'lodash.pick'
import { getAction, httpAction } from '@/api/manage'
import MemberFormBase from './components/MemberForm'

export default {
  name: 'MemberEditModal',
  components:{ MemberFormBase },
  data() {
    return {
      visible: false,
      model: {},
      form: this.$form.createForm(this),
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      offsetWrapperCol: {
        xs: { span: 24 },
        sm: { span: 16, offset: 5 }
      },
      confirmLoading: false,
      url: {
        add: '/member/add',
        edit: '/member/edit'
      }
    }
  },
  methods: {
    add() {
      this.edit({})
    },
    edit(record) {
      this.form.resetFields()
      this.model = Object.assign({}, record)
      this.visible = true
      this.$nextTick(() => {
        this.form.setFieldsValue(pick(this.model, 'name', 'gender', 'phone', 'remark'))
      })
    },
    close() {
      this.$emit('close')
      this.visible = false
    },
    handleCancel() {
      this.close()
    },
    handleOk() {
      this.form.validateFields((err, values) => {
        if (!err) {
          this.confirmLoading = true
          let httpurl = ''
          let method = ''
          if (!this.model.id) {
            httpurl += this.url.add
            method = 'post'
          } else {
            httpurl += this.url.edit
            method = 'put'
          }
          let formData = Object.assign(this.model, values)
          httpAction(httpurl, formData, method)
            .then((res) => {
              console.log(res)
              if (res.success) {
                this.$message.success(res.message)
                this.$emit('ok')
              } else {
                this.$message.warning(res.message)
              }
            })
            .finally(() => {
              this.confirmLoading = false
              this.close()
            })
        }
      })
    }
  }
}
</script>

点击提交居然没问题,可以收集到表单数据。有点出乎意料的顺利,我还以为需要调整一些内容,比如说把 $form.createForm 创建的表单 prop 进子组件。

因为使用了 v-decorator 来注册的表单控件,但当前组件并没有 Form 我想这可能会有数据接管的问题。

具体原因呢还没有看到,不过多半是和 Form.create 有关系。等有时间了再确定一下吧。