封装 ant desigin vue3中a-select,实现一级二级(单选,多选),以及自定义选项

组件:

<template>
  <a-select
      placeholder="请选择"
      :mode="selectType === 'check' ? 'multiple' : 'default'"
      :value="value"
      :options="formattedOptions"
      :open="isOpen"
      @click="handleSelectClick"
      @change="handleChange"
      show-search
      :field-names="fieldName"
  >
    <template v-if="value.includes('其他')" #dropdownRender="{ menuNode: menu }">
      <v-nodes :vnodes="menu" />
      <div
          style="width: 100%;display: flex;justify-content: space-around;margin: 5px 0px;align-items: center;"
      >
        <a-input class="input23" v-model:value="inputValue" style="width: 50%" />
        <a-button size="small" class="input23" @click.stop="submit" type="primary">确定</a-button>
      </div>
    </template>
  </a-select>
</template>

<script setup>
import { getCurrentInstance, onMounted, onUnmounted, ref, computed } from 'vue';

const { emit } = getCurrentInstance();
const isOpen = ref(false);
// eslint-disable-next-line no-undef
const props = defineProps({
  options: {
    type: Array,
    required: true
  },
  value: {
    type: [Array,String],
    required: false,
    default: () => []
  },
  selectType: {
    type: String,
    required: false,
    default: () => 'single'
  },
  valueType: {
    type: String,
    required: false,
    default: () => 'list'
  },
  fieldName: {
    type: Object,
    required: false,
  }
});
const inputValue = ref('');


const formattedOptions = computed(() => {
  if (props.valueType === 'obj') {
    return props.options;
  } else {
    return props.options.map(option => ({ label: option, value: option }));
  }
});


function submit() {
  isOpen.value = false;
  if (props.selectType === 'check') {
    const index = props.value.findIndex(item => item === '其他')
    let list = [...props.value]
    if (index !== -1) {
      list.splice(index, 1)
    }
    emit('update:value', [...list, inputValue.value])
  }
  else emit('update:value', inputValue.value)
}


const VNodes = (_, { attrs }) => {
  return attrs.vnodes;
};

function handleChange(val,) {
  
    isOpen.value = val.includes('其他') || props.selectType === 'check' ;
 
  emit('update:value', val);
}


function handleSelectClick() {
  if (isOpen.value) return;
  if (!isOpen.value) {
    isOpen.value = true
    return;
  }
  if (!props.value.includes('其他')) {
    isOpen.value = true;
  }
}

const handleGlobalClick = (event) => {
  const target = event.target;
  const selectNode = target.closest('.ant-select-selector');
  const optionNode = target.closest('.ant-select-item-option');
  const optionNode2 = target.closest('.input23');
  if (!optionNode2 && !selectNode && !optionNode && !props.value.includes('其他')) {
    isOpen.value = false;
  }
};

onMounted(() => {
  document.addEventListener('click', handleGlobalClick);
});

onUnmounted(() => {
  document.removeEventListener('click', handleGlobalClick);
});
</script>

其他页面使用:

1,单选:

 <SelectOther v-model:value="data.formState.papersType" :options="data.papersType" style="width: 200px"/>

2,多选:

<SelectOther v-model:value=""
             :options="data.chestSigns"
             :select-type="'check'" //多选
             style="margin: -5px 0;width: 120px"/>

3,二级下拉列表:

<SelectOther :value-type="'obj'"  //二级列表数据
             :field-name="{ 
                          label: 'name', 
                          value: 'name',
                          options: 'child' }"  //自定义二级数据格式
             style="width: 100%" 
             v-model:value="" 
             :options="options.drugName"/>

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值