vue 3.2动态 组件

<template>
  <component :is="getComponent()" class="full-width" v-bind="componentProps" />
</template>

<script setup name="DynamicInput">
import {
  Input,
  InputNumber,
  DatePicker,
  Select,
  Cascader
} from 'ant-design-vue'
import SSelectFetch from '@/components/UIComponents/SSelectFetch'
import MultipleCascader from '@/components/MultipleCascader'
import { selectTreeNode, tableDataList } from '@/api/common'

import { useAttrs } from 'vue'
const props = defineProps({
  item: {
    type: Object,
    default: () => {}
  }
})

const componentsMap = {
  String: Input,
  Number: InputNumber,
  Date: DatePicker,
  Select: Select,
  SearchSelect: SSelectFetch,
  Cascader: Cascader,
  MultipleCascader: MultipleCascader
}

const _propsMap = {
  String: {
    maxLength: 100,
    placeholder: '请输入'
  },
  Number: {
    placeholder: '请输入',
    min: 0,
    precision: 0
  },
  Date: {
    type: 'date',
    placeholder: '请选择日期'
  },
  Select: {
    placeholder: '请选择'
  },
  SearchSelect: {
    placeholder: '请输入关键字搜索',
    fieldNames: {
      label: 'name',
      value: 'id'
    }
  },
  Cascader: {
    placeholder: '请选择',
    fieldNames: {
      label: 'name',
      value: 'id',
      children: 'children'
    }
  },
  MultipleCascader: {
    placeholder: '请选择',
    fieldNames: {
      label: 'name',
      value: 'id',
      children: 'children'
    },
    maxTagCount: 1,
    maxTagTextLength: 4
  }
}

const districs = ref([])

async function loadDistricts() {
  const { data } = await selectTreeNode({})
  districs.value = data
}

function getComponent() {
  const { className, multipleFlag } = props.item
  if (className === 'Cascader') {
    if (multipleFlag === 'Y') {
      return MultipleCascader
    }
    return Cascader
  }
  return componentsMap[className]
}

const componentProps = computed(() => {
  const { className, multipleFlag, sourceKey, showFlag } = props.item
  const attrs = useAttrs()
  const baseProps = { ..._propsMap[className], ...attrs }
  if (className === 'Cascader') {
    if (multipleFlag === 'Y') {
      return {
        ...baseProps,
        options: districs.value,
        maxTagCount: 1,
        maxTagTextLength: 4,
        placeholder: '请选择地区',
        fieldNames: {
          label: 'name',
          value: 'id',
          children: 'children'
        }
      }
    } else {
      return {
        ...baseProps,
        options: districs.value,
        placeholder: '请选择地区',
        fieldNames: {
          label: 'name',
          value: 'id',
          children: 'children'
        },
        changeOnSelect: true,
        showSearch: {
          filter: (inputValue, path) => {
            return path.some(
              (option) =>
                option.label.toLowerCase().indexOf(inputValue.toLowerCase()) >
                -1
            )
          }
        }
      }
    }
  }
  if (className === 'SearchSelect') {
    return {
      ...baseProps,
      data: (params) =>
        tableDataList({
          ...params,
          sourceKey: sourceKey,
          showFlag: showFlag
        })
    }
  }
  return baseProps
})

onMounted(loadDistricts)
</script>

<style lang="scss" scoped>
.full-width {
  width: 100%;
}
</style>
import DynamicInput from './DynamicInput.vue'

 <a-col
    v-for="(item, index) in formState.dynamicsList"
     :key="item.id"
     :span="6"
   >
     <a-form-item
       :label="item.name"
       :name="['dynamicsList', index, item.code]"
       :rules="{
         required: item.requestFlag === 'Y',
         message: `请完善${item.name}`
       }"
     >
       <DynamicInput :item="item" v-model:value="item[item.code]" />
     </a-form-item>
   </a-col>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web_Hsir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值