Vue Antdv a-form 表单中使用自定义组件,并支持 v-decorator 效验

2,211 阅读1分钟

一、简介

  • Vue 自定义组件实现 v-model 数据双向绑定

  • 在使用 AntdvForm 表单的时候,有时候需要官方自带的组件未必够用。

  • 这个时候需要使用到自定义的一些组件,自定义的组件需要支持数据双向绑定,也需要支持 v-decorator 的数据效验,或者默认值设置等等。

二、自定义相关组件

  • CustomInput.vue:自定义一个输入框来举例

    <template>
      <!-- 包装一个 input,让它支持数据双向绑定 v-model,同时也支持 form 表单的效验 -->
      <div class="custom-input">
        <!-- 使用一个输入框 -->
        <a-input
          :placeholder="placeholder"
          v-model="valuePro"
          @change="inputChange"
        />
      </div>
    </template>
    
    <script>
    export default {
      // a-form 表单会监听下面事件与值,到时候需要通过 change 事件传出新的值即可,v-decorator 会通过 change 事件接受新值
      model: {
        prop: 'value',
        event: 'change'
      },
      props: {
        // 当前组件值
        // 默认是给 v-model 绑定值使用的
        value: {
          type: String
          // 当通过 a-from 标签包裹时:
          // 这个参数是 v-decorator 给子组件传值用的
          // 这里不要给默认值, 在 form 下使用会爆警告 Warning: SquareUpload `default value` can not collect,  please use `option.initialValue` to set default value.
        },
        // 占位符
        placeholder: {
          type: String,
          default: () => undefined
        }
      },
      computed: {
        // 支持 v-model 双向数据绑定,如果有新数据会通过 $emit 一个 input 事件进行修改 v-model 的值,也就是当前 value 值。
        // 写法是固定的,vue 自动处理,只管通过 $emit('input', newValue) 抛出去新的值即可。
        currentValue: {
          get () {
            return this.value
          },
          set (newValue) {
            this.$emit('input', newValue)
          }
        }
      },
      watch: {
        // 监听当前值变化,及时提交给父组件
        currentValue: {
          deep: true,
          immediate: true,
          handler: function (newValue) {
            // 记录最新的值
            this.valuePro = newValue
            // 判断当前的 value 值是否为 undefined, 如果是的话不用抛出去,要不然 form 标签就会走效验,并提示对应的错误了
            if (newValue !== undefined) {
              // v-decorator 会通过 change 事件接受新值
              this.$emit('change', newValue)
            }
          }
        }
      },
      data () {
        return {
          // 当前页面值,用于做桥梁使用的
          // 当前页面操作修改的就是这个值,外部传进来也会更新这个值,它变化了在通过 input change 去更新外部的值
          valuePro: undefined
        }
      },
      methods: {
        // input 输入
        inputChange (e) {
          // 传出去最新值,这里只需要通过 change 事件传出去即可,内部的 value 也会发生变化
          this.$emit('change', e.target.value)
        }
      }
    }
    </script>
    
  • home.vue:进行使用

    <template>
      <!-- form -->
      <a-form
        :form="form"
        :label-col="{ span: 3 }"
        :wrapper-col="{ span: 5 }"
        @submit="handleSubmit"
      >
        <!-- 原生组件 -->
        <a-form-item label="原生组件">
          <a-input
            placeholder="请输入名称"
            v-decorator="['name', { rules: [{ required: true, message: '请输入名称!' }] }]"
          />
        </a-form-item>
        <!-- 自定义组件 -->
        <a-form-item label="自定义组件">
          <custom-input
            placeholder="请输入简介"
            v-decorator="['info', { rules: [{ required: true, message: '请输入名称!' }] }]"
          />
        </a-form-item>
        <!-- 提交按钮 -->
        <a-form-item label="提交按钮">
          <a-button type="primary" html-type="submit">Submit</a-button>
        </a-form-item>
      </a-form>
    </template>
    
    <script>
    import CustomInput from './CustomInput'
    export default {
      components: {
        CustomInput
      },
      data () {
        return {
          // 创建一个 Form 对象
          form: this.$form.createForm(this)
        }
      },
      methods: {
        // 提交按钮
        handleSubmit(e) {
          e.preventDefault()
          // 效验数据
          this.form.validateFields((err, values) => {
            if (!err) {
              console.log('Form表单数据效验成功:', values)
            }
          })
        }
      }
    }
    </script>
    
  • 使用效果,跟官方封装的组件比较,使用基本没一致

    temp.gif