vue3+ts实现一个下拉选择框组件,支持搜索和多级联动

<template>
  <div class="multi-select-dropdown">
    <input type="text" v-model="searchText" @input="filterOptions" placeholder="搜索..." />
    <select v-model="selected" @change="handleChange">
      <option v-for="option in filteredOptions" :key="option.value" :value="option.value">
        {{ option.label }}
      </option>
    </select>
    <div v-if="showSubOptions" class="sub-options">
      <!-- 子级下拉框 -->
      <select v-model="selectedSubOption">
        <option v-for="subOption in subOptions" :key="subOption.value" :value="subOption.value">
          {{ subOption.label }}
        </option>
      </select>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';

// 定义 props
const props = defineProps<{
  options: Array<{ value: string; label: string; children?: Array<{ value: string; label: string }> }>;
}>();

// 定义 emits
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void;
  (e: 'change', value: string): void;
}>();

// 数据
const searchText = ref('');
const selected = ref('');
const showSubOptions = ref(false);
const selectedSubOption = ref('');

// 计算属性
const filteredOptions = computed(() => {
  return props.options.filter(option => option.label.includes(searchText.value));
});

// 方法
const handleChange = () => {
  const selectedOption = props.options.find(option => option.value === selected.value);
  if (selectedOption && selectedOption.children) {
    showSubOptions.value = true;
  } else {
    showSubOptions.value = false;
  }
  emit('change', selected.value);
};

const filterOptions = () => {
  // 根据搜索文本过滤选项
};

// 监听 selected 的变化,更新父组件
watch(selected, (newValue) => {
  emit('update:modelValue', newValue);
});
</script>

<style scoped>
.multi-select-dropdown {
  /* 样式 */
}
.sub-options {
  /* 子级下拉框样式 */
}
</style>

在这个组件中,我们使用了 defineProps 来定义组件的属性,defineEmits 来定义组件可以触发的事件。组件内部使用了 refcomputed 来管理数据和计算属性,以及 watch 来监听数据变化并更新父组件。

父组件可以通过 v-model 或事件监听来与这个子组件进行交互。例如:

<template>
  <div>
    <multi-select-dropdown :options="options" v-model="selectedValue" @change="handleChange" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import MultiSelectDropdown from './MultiSelectDropdown.vue';

const options = [
  { value: '1', label: '选项1', children: [{ value: '1-1', label: '子选项1-1' }] },
  { value: '2', label: '选项2', children: [{ value: '2-1', label: '子选项2-1' }] },
  // 更多选项...
];

const selectedValue = ref('');

const handleChange = (value: string) => {
  console.log('Selected value changed to:', value);
};
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

温暖前端

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

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

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

打赏作者

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

抵扣说明:

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

余额充值