ant design vue 1.x 和 3.x 自定义表单示例

以下是项目中用到的自定义表单的写法,vue2 vue3 各记录一个。

1.x(For vue2)

自定义表单的示例

实现如下图的控件

代码如下:

import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import { Moment } from 'moment'

type Value = { left: Moment; right: Moment }

@Component
export default class TimeRange extends Vue {
  @Prop(Object) readonly value!: Value
  public left = this.value.left
  public right = this.value.right

  @Watch('value')
  onValueChange (val: Value) {
    this.left = val.left
    this.right = val.right
  }

  handleLeftChange (left: Moment) {
    this.left = left
  }

  handleRightChange (right: Moment) {
    this.right = right
  }

  triggerChange (changedValue: {
    [K in keyof Value]: Moment
  }) {
    this.$emit('change', Object.assign({}, this.$data, changedValue))
  }

  openChangeHandle (open: boolean) {
    if (open) {
      this.$emit('focus')
    } else {
      this.checkTimeValue()
    }
  }

  checkTimeValue () {
    const { left, right } = this
    if (left.isAfter(right)) {
      this.triggerChange({
        left: right,
        right: left
      })
    } else {
      this.triggerChange({
        left,
        right
      })
    }
  }

  render () {
    const { left, right } = this

    return <span>
      <a-time-picker
        allowClear={false}
        format="HH:mm"
        value={left}
        onOpenChange={this.openChangeHandle}
        onChange={this.handleLeftChange} />
      <span> - </span>
      <a-time-picker
        allowClear={false}
        format="HH:mm"
        value={right}
        onOpenChange={this.openChangeHandle}
        onChange={this.handleRightChange}
      />
    </span>
  }
}

3.x (vue3)

自定义表单的示例

实现如下图的控件

<template>
  <a-form-item-rest>
    <a-input-number
      :value="value[0]"
      :min="0"
      @change="onLeftNumberChange"
      @blur="blur"
    ></a-input-number>
    -
    <a-input-number
      :value="value[1]"
      :min="0"
      @change="onRightNumberChange"
      @blur="blur"
    ></a-input-number>
  </a-form-item-rest>
</template>
<script lang="ts" src="./index.ts"></script>
<style lang="less" scoped></style>
import { Form } from "ant-design-vue";
import { defineComponent, PropType } from "vue";

export type RangeNumberValue = number | null;

export default defineComponent({
  name: "h-number-range",
  props: {
    value: {
      type: Array as unknown as PropType<[RangeNumberValue, RangeNumberValue]>,
      required: true,
    },
  },
  emits: ["update:value"],
  setup(props, { emit }) {
    const formItemContext = Form.useInjectFormItemContext();
    const triggerChange = (
      changedValue: [RangeNumberValue, RangeNumberValue]
    ) => {
      emit("update:value", [...changedValue]);
      formItemContext.onFieldChange();
    };

    const blur = () => {
      let [left, right] = props.value;

      // 保证右 >= 左
      if (left !== null && right !== null && left > right) {
        const temp = left;
        left = right;
        right = temp;
      }

      triggerChange([left, right]);
    };

    const onLeftNumberChange = (value: RangeNumberValue) => {
      triggerChange([value, props.value[1]]);
    };
    const onRightNumberChange = (value: RangeNumberValue) => {
      triggerChange([props.value[0], value]);
    };
    return {
      onLeftNumberChange,
      onRightNumberChange,
      blur,
    };
  },
});
posted @ 2023-11-21 11:14  Shapeying  阅读(266)  评论(0编辑  收藏  举报