用vue3和ts写一个支持可输入、可全选的下拉框,多选的值在输入框中用英文逗号隔开,回答全
时间: 2023-05-13 13:05:52 浏览: 361
以下是一个用 Vue3 和 TypeScript 编写的支持可输入、可全选的下拉框,多选的值在输入框中用英文逗号隔开的示例代码:
```html
<template>
<div class="select-wrapper">
<input type="text" v-model="inputValue" @input="handleInput" @keydown.enter="handleEnter" @keydown.tab="handleTab" @keydown.esc="handleEsc" @keydown.down="handleDown" @keydown.up="handleUp" />
<ul class="options" v-show="isOpen">
<li v-for="(option, index) in filteredOptions" :key="index" :class="{ active: index === activeIndex }" @mousedown="handleMouseDown(index)">
{{ option }}
</li>
</ul>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed, watch } from 'vue'
export default defineComponent({
name: 'Select',
props: {
options: {
type: Array,
required: true,
},
value: {
type: [String, Array],
default: '',
},
multiple: {
type: Boolean,
default: false,
},
},
setup(props, { emit }) {
const inputValue = ref<string>(props.value as string)
const isOpen = ref<boolean>(false)
const activeIndex = ref<number>(-1)
const filteredOptions = computed(() => {
return props.options.filter((option) => {
return option.toLowerCase().includes(inputValue.value.toLowerCase())
})
})
const handleInput = (event: InputEvent) => {
const target = event.target as HTMLInputElement
inputValue.value = target.value
activeIndex.value = -1
}
const handleEnter = () => {
if (activeIndex.value !== -1) {
handleSelect(filteredOptions.value[activeIndex.value])
}
}
const handleTab = () => {
if (activeIndex.value !== -1) {
handleSelect(filteredOptions.value[activeIndex.value])
} else {
isOpen.value = false
}
}
const handleEsc = () => {
isOpen.value = false
}
const handleDown = () => {
if (activeIndex.value < filteredOptions.value.length - 1) {
activeIndex.value++
}
}
const handleUp = () => {
if (activeIndex.value > -1) {
activeIndex.value--
}
}
const handleSelect = (option: string) => {
if (props.multiple) {
const values = (props.value as string).split(',')
if (values.includes(option)) {
values.splice(values.indexOf(option), 1)
} else {
values.push(option)
}
inputValue.value = values.join(',')
} else {
inputValue.value = option
isOpen.value = false
}
emit('update:value', inputValue.value)
}
const handleMouseDown = (index: number) => {
handleSelect(filteredOptions.value[index])
}
watch(
() => props.value,
(newValue) => {
inputValue.value = newValue as string
}
)
return {
inputValue,
isOpen,
activeIndex,
filteredOptions,
handleInput,
handleEnter,
handleTab,
handleEsc,
handleDown,
handleUp,
handleSelect,
handleMouseDown,
}
},
})
</script>
<style scoped>
.select-wrapper {
position: relative;
}
.options {
position: absolute;
top: 100%;
left: 0;
z-index: 1;
list-style: none;
padding: 0;
margin: 0;
background-color: #fff;
border: 1px solid #ccc;
border-top: none;
max-height: 200px;
overflow-y: auto;
}
.options li {
padding: 5px;
cursor: pointer;
}
.options li.active {
background-color: #f2f2f2;
}
input[type='text'] {
width: 100%;
box-sizing: border-box;
padding: 5px;
border: 1px solid #ccc;
}
</style>
```
使用方法:
```html
<template>
<div>
<select v-model="selectedOptions" multiple>
<option v-for="option in options" :value="option">{{ option }}</option>
</select>
<select v-model="selectedOption">
<option v-for="option in options" :value="option">{{ option }}</option>
</select>
<Select :options="options" v-model="selectedOptions" multiple />
<Select :options="options" v-model="selectedOption" />
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Select from './Select.vue'
export default defineComponent({
name: 'App',
components: {
Select,
},
setup() {
const options = ref<string[]>(['Apple', 'Banana', 'Cherry', 'Durian', 'Elderberry'])
const selectedOptions = ref<string[]>([])
const selectedOption = ref<string>('')
return {
options,
selectedOptions,
selectedOption,
}
},
})
</script>
```
在这个示例中,我们使用了 Vue3 的 Composition API,定义了一个名为 `Select` 的组件,它接受 `options`、`value` 和 `multiple` 三个 props,分别表示下拉框的选项、选中的值和是否支持多选。组件内部使用了 `ref`、`computed` 和 `watch` 等响应式 API,实现了下拉框的各种交互逻辑。在使用时,我们可以像使用普通的 `select` 元素一样使用 `Select` 组件,并通过 `v-model` 双向绑定选中的值。
阅读全文