美文网首页
vue3 + ant-design-vue自定义组合表单项for

vue3 + ant-design-vue自定义组合表单项for

作者: 很好就这样吧 | 来源:发表于2023-11-27 11:37 被阅读0次

效果图:

重点:
1、父级rc-form-item 上不要加 prop,要分别加在内部的各个表单元素上

2、自定组件内部表单元素上的prop写法要用这种拼接的方式
:prop="props.attValName + '.selectVal'"
:prop="props.attValName + '.' + index + '.value'"
而不是下面这种,下面的写法无法触发校验
:prop="props.attValName[ index ].value'"

3、要达到父级form能控制自定义组件内部的各个表单元素的校验和数据回显、重置等能力,
自定义组件的state定义的数据格式尤为重要,以地址级联组件AttrAddress为例:
emit('update:modelValue', state.attVals)
即props.modelValue 所包含的数据,要被state.attVals全部包含,这样就可以由父级的form完全托管校验重置等能力。

源码:
index.vue

<template>
  <!-- 自定义组件 使用样例 -->
  <div>
    <rc-form ref="formRef" :model="form" :rules="rules" label-width="146px">
      <rc-form-item label-width="0">
        <!-- 注意这里的 rc-form-item 不要加prop 做规则校验,通过required控制是否必填,内部校验-->
        <AttrSelectAlias
          v-model="form.attrSelectAlias"
          :att-id="238290"
          att-name="属性值可别名"
          att-val-name="attrSelectAlias"
          :required="true"
          extra=""
        />
      </rc-form-item>
      <rc-form-item label-width="0">
        <!-- 注意这里的 rc-form-item 不要加prop 做规则校验,通过required控制是否必填,内部校验-->
        <AttrSelectPercent
          v-model="form.attrSelectPercent"
          :att-id="217746"
          att-name="复选百分比"
          att-val-name="attrSelectPercent"
          :required="true"
          extra=""
          label-width="146px"
        />
      </rc-form-item>

      <rc-form-item label-width="0">
        <!-- 注意这里的 rc-form-item 不要加prop 做规则校验,通过required控制是否必填,内部校验-->
        <AttrCombinedInputs
          v-model="form.combinedInputs2"
          extra=""
          :att-id="238296"
          att-name="组合输入框有前缀"
          att-val-name="combinedInputs2"
          :required="true"
          :prefix-list="prefixList2"
          :unit-list="unitList1"
        />
      </rc-form-item>

      <rc-form-item label-width="0">
        <!-- 注意这里的 rc-form-item 不要加prop 做规则校验,通过required控制是否必填,内部校验-->
        <AttrCascader
          v-model="form.cascader"
          :att-id="238291"
          att-name="级联选择"
          att-val-name="cascader"
          :required="true"
          label-width="146px"
        />
      </rc-form-item>

      <rc-form-item label-width="0">
        <!-- 注意这里的 rc-form-item 不要加prop 做规则校验,通过required控制是否必填,内部校验-->
        <AttrAddress
          v-model="form.attrAddress2"
          :att-id="238841"
          att-name="地址级联选择4级"
          att-val-name="attrAddress2"
          :level="4"
          :required="true"
          label-width="146px"
        />
      </rc-form-item>

      <rc-form-item>
        <rc-button type="primary" size="large" @click="submitForm(formRef)"> 提交 </rc-button>
        <rc-button plain size="large" @click="resetForm(formRef)"> 重置 </rc-button>
      </rc-form-item>
    </rc-form>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'ant-design-vue'

import AttrSelectAlias from './components/AttrSelectAlias/index.vue'
import AttrSelectPercent from './components/AttrSelectPercent/index.vue'
import AttrCombinedInputs, {
  prefixList1,
  prefixList2,
  unitList1,
} from './components/AttrCombinedInputs/index.vue'
import AttrCascader from './components/AttrCascader/index.vue'
import AttrAddress from './components/AttrAddress/index.vue'

const formRef = ref<FormInstance>()
const form = reactive({
  attrSelectAlias: { selectVal: '1093079', alias: '我是别名' },
  // attrSelectAlias: undefined,
  attrSelectPercent: [], // 复选百分比
  // combinedInputs2:undefined,
  combinedInputs2: [
    { prefix: '长', value: '100', valueUnit: 'cm' },
    { prefix: '宽', value: '50', valueUnit: 'ml' },
    { prefix: '高', value: '10', valueUnit: 'cm' },
  ],
  // cascader: undefined, // 级联选择
  cascader: [1093079, 1093081], // 级联选择
  attrAddress2: { address: ['1', '2901', '55549'], isOverSea: false },
})
const rules = reactive<FormRules>({})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!===', form)
    } else {
      console.log('error submit!-fields', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
</script>
<style lang="scss" scoped></style>

./components/AttrSelectAlias/index.vue

<template>
  <!-- 属性值 可别名:下拉选择框 + 输入框 -->
  <rc-form-item
    :label="props.attName"
    :prop="props.attValName + '.selectVal'"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-select
      v-model="state.attVal.selectVal"
      placeholder="请选择"
      :multiple="props.multiple"
      clearable
      style="width: 320px"
      @change="onSelectChange"
    >
      <rc-option
        v-for="item in state.options"
        :key="item.id"
        :label="item.name"
        :value="item.id.toString()"
      />
    </rc-select>
  </rc-form-item>

  <rc-form-item
    style="margin-left: 8px"
    :prop="props.attValName + '.alias'"
    :rules="{
      required: props.required,
      message: '请输入别名',
      trigger: 'blur',
    }"
  >
    <rc-input
      v-model="state.attVal.alias"
      placeholder="请输入别名"
      style="width: 320px"
      @input="onInputChange"
    />
  </rc-form-item>

  <div v-if="extra" class="extra"> 备注&示例:{{ extra }} </div>
</template>

<script lang="ts">
interface AttValue {
  selectVal: string
  alias: string
}
interface AttValueItem {
  id: number
  name: string
}
</script>
<script setup lang="ts">
import { onMounted, reactive } from 'vue'
import mockData from '../../mock.json'

const props = defineProps({
  modelValue: {
    type: Object,
    default: undefined,
  },
  attId: {
    type: Number,
    default: undefined,
  },
  attName: {
    type: String,
    default: undefined,
  },
  attValName: {
    type: String,
    default: undefined,
  },
  required: {
    type: Boolean,
    default: false,
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  extra: {
    type: String,
    default: '',
  },
  labelWidth: {
    type: String,
    default: '',
  },
})
const emit = defineEmits(['update:modelValue', 'change', 'blur'])

const state = reactive<{
  attVal: AttValue
  options: AttValueItem[]
}>({
  attVal: { selectVal: '', alias: '' },
  options: [],
})
onMounted(() => {
  getData()
})

const getData = () => {
  if (!props.attId) return
  // 接口获取选择框下拉选项
  setTimeout(() => {
    state.options = mockData
    initAttVal()
  }, 300)
}

const initAttVal = () => {
  // console.log('props.modelValue===', props.modelValue)
  if (!props.modelValue || props.modelValue?.length == 0) {
    // 初始没有值
    state.attVal = { selectVal: '', alias: '' }
  } else {
    // 回显
    state.attVal = props.modelValue as AttValue
  }

  emit('update:modelValue', state.attVal)
  emit('change')
}

const onInputChange = () => {
  // console.log('onInputChange===', state.alias)
}
const onSelectChange = () => {
  // console.log('onSelectChange===', state.selectVal)
}
</script>
<style lang="scss" scoped>
.extra {
  margin-left: 8px;
  color: var(--rcd-color-text-200);
  font-size: 12px;
}
</style>

./components/AttrSelectPercent/index.vue

<template>
  <!-- 复选百分比:选择框+输入框+%  -->
  <rc-form-item
    v-for="(attVal, index) in state.attVals"
    :key="index"
    :style="{ marginBottom: index == state.attVals.length - 1 ? '0' : '20px' }"
  >
    <rc-form-item
      :label="index == 0 ? props.attName : ''"
      :prop="props.attValName + '.' + index + '.value'"
      :rules="{
        required: props.required,
        message: '请选择',
        trigger: 'change',
      }"
      :label-width="props.labelWidth"
    >
      <rc-select
        v-model="state.attVals[index].value"
        placeholder="请选择"
        :style="{
          width: '220px',
        }"
        @change="onSelectChange"
      >
        <rc-option
          v-for="item in state.options"
          :key="item.id"
          :label="item.name"
          :value="item.id.toString()"
        />
      </rc-select>
    </rc-form-item>

    <rc-form-item
      :prop="props.attValName + '.' + index + '.percentage'"
      :rules="{
        required: props.required,
        message: '请输入',
        trigger: 'blur',
      }"
    >
      <rc-input
        v-model="state.attVals[index].percentage"
        placeholder="请输入"
        class="input"
        :maxlength="3"
        @change="onInputChange"
      >
        <template #append> % </template>
      </rc-input>

      <rc-button style="margin-left: 8px" @click.prevent="removeDomain(attVal)"> 删除 </rc-button>
    </rc-form-item>
  </rc-form-item>
  <rc-button style="margin-left: 8px" @click="addDomain"> 新增 </rc-button>

  <div v-if="extra" class="extra"> 备注&示例:{{ extra }} </div>
</template>

<script lang="ts">
interface AttValItem {
  value: string
  percentage: string
  valUnit: string
}
interface AttValueItem {
  id: number
  name: string
}
</script>

<script setup lang="ts">
import { reactive, onMounted } from 'vue'
import mockData from '../../mock.json'

const props = defineProps({
  modelValue: {
    type: Array,
    default: undefined,
  },
  attId: {
    type: Number,
    default: undefined,
  },
  attName: {
    type: String,
    default: undefined,
  },
  attValName: {
    type: String,
    default: undefined,
  },
  required: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  extra: {
    type: String,
    default: '',
  },
  labelWidth: {
    type: String,
    default: '',
  }
})
const emit = defineEmits(['update:modelValue', 'change'])

const state = reactive<{
  attVals: AttValItem[]
  options: AttValueItem[]
}>({
  attVals: [],
  options: [],
})

onMounted(() => {
  getData()
})

const removeDomain = (item: AttValItem) => {
  const index = state.attVals.indexOf(item)
  if (index !== -1) {
    state.attVals.splice(index, 1)
  }
}

const addDomain = () => {
  state.attVals.push({ value: '', percentage: '', valUnit: '%' })
}

const getData = () => {
  if (!props.attId) return
  // 接口获取选择框下拉选项
  setTimeout(()=>{
    state.options = mockData
    initAttVal()

    emit('update:modelValue', state.attVals)
    emit('change')
  },300)
}

const initAttVal = () => {
  // console.log('props.modelValue===', props.modelValue)
  if (!props.modelValue || props.modelValue?.length == 0) {
    // 初始没有值
    addDomain()
  } else {
    // 回显
    state.attVals = props.modelValue as AttValItem[]
  }
}

const onInputChange = () => {
  // console.log('onInputChange===', state.attVal)
}
const onSelectChange = () => {
  // console.log('onSelectChange===', state.attVal)
}
</script>
<style lang="scss" scoped>
.extra {
  margin-left: 8px;
  color: var(--rcd-color-text-200);
  font-size: 12px;
}
.input {
  width: 104px;
  margin-left: -4px;
  :deep(.rcd-input__wrapper) {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
}
</style>

./components/AttrCombinedInputs/index.vue

<template>
  <!-- 组合类型:前缀(+/-/''/长/宽/高) + 输入框 + 单位下拉选择框  -->
  <rc-form-item v-for="(prefix, index) in state.prefixList" :key="index">
    <rc-form-item
      :label="index == 0 ? props.attName : ''"
      :prop="props.attValName + '.' + index + '.value'"
      :rules="{
        required: props.required,
        message: '请输入',
        trigger: 'blur',
      }"
    >
      <rc-input
        v-model="state.attVal[index].value"
        placeholder="请输入"
        :style="{ width: state.prefixList.length == 1 ? '320px' : '200px' }"
        @change="onInputChange"
      >
        <template v-if="prefix" #prepend>
          <div style="width: 14px">
            {{ prefix }}
          </div>
        </template>
        <template #append>
          <rc-select style="width: 71px" />
        </template>
      </rc-input>
    </rc-form-item>
    <rc-form-item :prop="props.attValName + '.' + index + '.valueUnit'">
      <rc-select
        v-model="state.attVal[index].valueUnit"
        class="select"
        :style="{ marginRight: index == state.prefixList.length - 1 ? 0 : '24px' }"
        @change="onUnitChange"
      >
        <rc-option v-for="(unit, idx) in state.unitList" :key="idx" :label="unit" :value="unit" />
      </rc-select>
    </rc-form-item>
  </rc-form-item>

  <div v-if="extra" class="extra"> 备注&示例:{{ extra }} </div>
</template>

<script lang="ts">
interface AttValItem {
  prefix: string
  value: string
  valueUnit: string
}
// 自测数据
export const prefixList2 = ['长', '宽', '高'] // 有前缀
export const prefixList1 = [''] // 没有前缀
export const unitList1 = ['mm', 'cm', 'm']
</script>

<script setup lang="ts">
import { reactive, onMounted } from 'vue'

const props = defineProps({
  modelValue: {
    type: Array,
    default: undefined,
  },
  attId: {
    type: Number,
    default: undefined,
  },
  attName: {
    type: String,
    default: undefined,
  },
  attValName: {
    type: String,
    default: undefined,
  },
  required: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  prefixList: {
    type: Array,
    default() {
      return []
    },
  },
  unitList: {
    type: Array,
    default() {
      return []
    },
  },
  extra: {
    type: String,
    default: '',
  },
})
const emit = defineEmits(['update:modelValue', 'change'])

const state = reactive({
  attVal: [] as AttValItem[],
  prefixList: [] as string[],
  unitList: [] as string[],
})

onMounted(() => {
  getData()
})

const getData = () => {
  setTimeout(() => {
    state.prefixList = props.prefixList as string[]
    state.unitList = props.unitList as string[]

    initAttVal()

    emit('update:modelValue', state.attVal)
    emit('change')
  }, 1000)
}

const initAttVal = () => {
  // console.log('props.modelValue===', props.modelValue)
  if (!props.modelValue || props.modelValue?.length == 0) {
    // 初始没有值
    state.attVal = state.prefixList.map((prefix) => {
      return { prefix, value: '', valueUnit: state.unitList[0] }
    })
  } else {
    // 回显
    state.attVal = state.prefixList.map((prefix) => {
      const temp = props.modelValue?.find((item: any) => item.prefix == prefix) as AttValItem
      return { prefix, value: temp?.value, valueUnit: temp?.valueUnit }
    })
  }
}

const onInputChange = () => {
  // console.log('onInputChange===', state.attVal)
}
const onUnitChange = () => {
  // console.log('onUnitChange===', state.attVal)
}
</script>
<style lang="scss" scoped>
.extra {
  margin-left: 8px;
  color: var(--rcd-color-text-200);
  font-size: 12px;
}

.select {
  width: 72px;
  margin-left: -72px;
  z-index: 2;

  :deep(.rcd-input__wrapper) {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
}
</style>

./components/AttrCascader/index.vue

<template>
  <!-- 针对动态获取数据,且级联层级不确定的情况,有的选项层级多,有的选项层级少 -->
  <rc-form-item
    :label="props.attName"
    :prop="props.attValName + '.' + 0"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
    :label-width="props.labelWidth"
  >
    <rc-select
      v-model="state.attVals[0]"
      placeholder="请选择"
      :disabled="props.disabled"
      style="width: 320px; margin-right: 8px"
      @change="onChange1"
    >
      <rc-option
        v-for="item in option.options1"
        :key="item.id"
        :label="item.name"
        :value="item.id"
      />
    </rc-select>
  </rc-form-item>
  <rc-form-item
    v-if="option.options2.length > 0"
    :prop="props.attValName + '.' + 1"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-select
      v-model="state.attVals[1]"
      placeholder="请选择"
      :disabled="props.disabled"
      style="width: 320px"
      @change="onChange2"
    >
      <rc-option
        v-for="item in option.options2"
        :key="item.id"
        :label="item.name"
        :value="item.id"
      />
    </rc-select>
  </rc-form-item>

  <div v-if="extra" class="extra"> 备注&示例:{{ extra }} </div>
</template>

<script lang="ts">
interface AttValueByLevelItem {
  id: number
  name: string
}
</script>
<script setup lang="ts">
import { onMounted, reactive } from 'vue'
import mockData from '../../mock.json'

const props = defineProps({
  modelValue: {
    type: Array,
    default: undefined,
  },
  attId: {
    type: Number,
    default: undefined,
  },
  attName: {
    type: String,
    default: undefined,
  },
  attValName: {
    type: String,
    default: undefined,
  },
  required: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  extra: {
    type: String,
    default: '',
  },
  labelWidth: {
    type: String,
    default: '',
  },
})
const emit = defineEmits(['update:modelValue', 'change'])

const state = reactive({
  attVals: [] as number[],
})

const option = reactive<{ [key: string]: AttValueByLevelItem[] }>({
  options1: [],
  options2: [],
})

const getData = (level: number, parentId?: number, cb?: (hasNext: boolean) => void) => {
  // const params = {
  //   attId: props.attId,
  //   attLevel: level,
  //   parentId,
  // }
  // getAttValueByLevel(params).then((res) => {
  //   option['options' + level] = res || []
  //   cb && cb(res ? true : false)
  // })
  setTimeout(()=>{
    const res = mockData
    option['options' + level] = res || []
    cb && cb(res ? true : false)
  },300)
}

const onChange1 = (val: number) => {
  state.attVals.splice(1, 1) // 删掉第二个
  option.options2 = []
  getData(2, val)
}
const onChange2 = (val: number) => {
  //
}

const initAttVal = () => {
  // console.log('props.modelValue===', props.modelValue)
  if (!props.modelValue || props.modelValue?.length == 0) {
    // 初始没有值
  } else {
    // 回显
    state.attVals = props.modelValue as number[]
    if (props.modelValue.length > 1) {
      getData(2, state.attVals[0])
    }
  }
}

onMounted(() => {
  getData(1, undefined, () => {
    initAttVal()
    emit('update:modelValue', state.attVals)
    emit('change')
  })
})
</script>
<style lang="scss" scoped>
.extra {
  margin-left: 8px;
  color: var(--rcd-color-text-200);
  font-size: 12px;
}
</style>

./components/AttrAddress/index.vue

<template>
  <!-- 地址级联选择,动态获取下一级,且层级数不定,可能3级可能4级 -->
  <rc-form-item
    style="width: 100%"
    :label="props.attName"
    :label-width="props.labelWidth"
    :prop="props.attValName + '.isOverSea'"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-radio-group v-model="state.attVals.isOverSea" @change="onIsOverSeaChange">
      <rc-radio :label="false"> 国内 </rc-radio>
      <rc-radio :label="true"> 海外 </rc-radio>
    </rc-radio-group>
  </rc-form-item>

  <rc-form-item
    :label-width="props.labelWidth"
    :prop="props.attValName + '.address.' + 0"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-select
      v-model="state.attVals.address[0]"
      placeholder="请选择"
      style="width: 200px; margin-right: 8px"
      @change="(v: any) => onChange(v, 0 + 1)"
    >
      <rc-option
        v-for="item in option['options' + (0 + 1)]"
        :key="item.districtId"
        :label="item.districtName"
        :value="item.districtId.toString()"
      />
    </rc-select>
  </rc-form-item>

  <rc-form-item
    v-if="option.options2.length > 0"
    :prop="props.attValName + '.address.' + 1"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-select
      v-model="state.attVals.address[1]"
      placeholder="请选择"
      style="width: 200px; margin-right: 8px"
      @change="(v: any) => onChange(v, 1 + 1)"
    >
      <rc-option
        v-for="item in option['options' + (1 + 1)]"
        :key="item.districtId"
        :label="item.districtName"
        :value="item.districtId.toString()"
      />
    </rc-select>
  </rc-form-item>

  <rc-form-item
    v-if="option.options3.length > 0"
    :prop="props.attValName + '.address.' + 2"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-select
      v-model="state.attVals.address[2]"
      placeholder="请选择"
      style="width: 200px; margin-right: 8px"
      @change="(v: any) => onChange(v, 2 + 1)"
    >
      <rc-option
        v-for="item in option['options' + (2 + 1)]"
        :key="item.districtId"
        :label="item.districtName"
        :value="item.districtId.toString()"
      />
    </rc-select>
  </rc-form-item>

  <rc-form-item
    v-if="option.options4.length > 0"
    :prop="props.attValName + '.address.' + 3"
    :rules="{
      required: props.required,
      message: '请选择',
      trigger: 'change',
    }"
  >
    <rc-select
      v-model="state.attVals.address[3]"
      placeholder="请选择"
      style="width: 200px"
      @change="(v: any) => onChange(v, 3 + 1)"
    >
      <rc-option
        v-for="item in option['options' + (3 + 1)]"
        :key="item.districtId"
        :label="item.districtName"
        :value="item.districtId.toString()"
      />
    </rc-select>
  </rc-form-item>

  <div v-if="extra" class="extra"> 备注&示例:{{ extra }} </div>
</template>

<script setup lang="ts">
import { onMounted, reactive } from 'vue'
import { getAddressByParentId } from '@/services/productIntroduction'

const props = defineProps({
  modelValue: {
    type: Object,
    default: undefined,
  },
  attId: {
    type: Number,
    default: undefined,
  },
  // 可选层级
  level: {
    type: Number,
    default: 1,
  },
  attName: {
    type: String,
    default: undefined,
  },
  attValName: {
    type: String,
    default: undefined,
  },
  required: {
    type: Boolean,
    default: false,
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  extra: {
    type: String,
    default: '',
  },
  labelWidth: {
    type: String,
    default: '',
  },
})
const emit = defineEmits(['update:modelValue', 'change'])

interface AttValue {
  address: string[]
  isOverSea: boolean
}

const state = reactive<{ attVals: AttValue }>({
  attVals: {
    address: [],
    isOverSea: false,
  },
})

interface AddressItem {
  districtId: number
  districtName: string
  districtFatherId: number
}
const option = reactive<{ [key: string]: AddressItem[] }>({
  options1: [],
  options2: [],
  options3: [],
  options4: [],
})

const getData = (parentId: string, level: number, cb?: (hasNext: boolean) => void) => {
  getAddressByParentId({ parentId }).then((res) => {
    option['options' + level] = res.output?.areas || []
    cb && cb(res.output?.areas ? true : false)
  })
}

const onChange = (val: string, level: number) => {
  switch (level) {
    case 1:
      onChange1(val)
      break
    case 2:
      onChange2(val)
      break
    case 3:
      onChange3(val)
      break
    case 4:
      onChange4(val)
      break
  }
}

const onChange1 = (val: string) => {
  if (props.level <= 1) {
    //
  } else {
    // 截取数组,指定长度
    const len = state.attVals.address.length
    state.attVals.address.splice(1, len - 1)

    option.options2 = []
    option.options3 = []
    option.options4 = []

    getData(val, 2)
  }
}
const onChange2 = (val: string) => {
  if (props.level <= 2) {
    //
  } else {
    const len = state.attVals.address.length
    state.attVals.address.splice(2, len - 2)

    option.options3 = []
    option.options4 = []

    getData(val, 3)
  }
}
const onChange3 = (val: string) => {
  if (props.level <= 3) {
    //
  } else {
    const len = state.attVals.address.length
    state.attVals.address.splice(3, len - 3)

    option.options4 = []

    getData(val, 4)
  }
}
const onChange4 = (val: string) => {
  //
}

const onIsOverSeaChange = (isOverSea: number) => {
  // 重置地址选择框
  const len = state.attVals.address.length
  state.attVals.address.splice(0, len)
  option.options1 = []
  option.options2 = []
  option.options3 = []
  option.options4 = []
  const parentId = isOverSea ? '53283' : '4744'
  getData(parentId, 1) // 获取第一级选项
}

const initAttVal = () => {
  // console.log('props.modelValue===', props.modelValue)
  if (!props.modelValue) {
    // 初始没有值
  } else {
    // 回显
    state.attVals = props.modelValue as AttValue
    if (state.attVals.address.length > 1) {
      getData(state.attVals.address[0], 2)
    }
    if (state.attVals.address.length > 2) {
      getData(state.attVals.address[1], 3)
    }
    if (state.attVals.address.length > 3) {
      getData(state.attVals.address[2], 4)
    }
  }
}

onMounted(() => {
  const parentId = props.modelValue?.isOverSea ? '53283' : '4744'

  getData(parentId, 1, () => {
    initAttVal()
    emit('update:modelValue', state.attVals)
    emit('change')
  })
})
</script>
<style lang="scss" scoped>
.extra {
  margin-left: 8px;
  color: var(--rcd-color-text-200);
  font-size: 12px;
}
</style>

mock.json

[
    {
        "id": 1093079,
        "name": "测试1"
    },
    {
        "id": 1093080,
        "name": "测试2"
    },
    {
        "id": 1093081,
        "name": "测试3"
    }
]

相关文章

网友评论

      本文标题:vue3 + ant-design-vue自定义组合表单项for

      本文链接:https://www.haomeiwen.com/subject/amgawdtx.html