用vue3和ts写一个支持可输入、可全选的下拉框,多选的值在输入框中用英文逗号隔开
时间: 2023-05-13 15:05:50 浏览: 402
input+select(multiple) 实现下拉框输入值
以下是一个使用 Vue3 和 TypeScript 编写的支持可输入、可全选的下拉框,多选的值在输入框中用英文逗号隔开的示例代码:
```html
<template>
<div class="dropdown">
<input
type="text"
class="dropdown-input"
placeholder="请选择或输入"
v-model="inputValue"
@focus="showDropdown = true"
@blur="onInputBlur"
@keydown.enter.prevent="onEnterKeydown"
@keydown.down.prevent="onArrowDownKeydown"
@keydown.up.prevent="onArrowUpKeydown"
/>
<div
class="dropdown-menu"
v-show="showDropdown"
@mousedown.prevent
@mouseup.prevent
@click="onMenuClick"
>
<div
class="dropdown-item"
v-for="(item, index) in filteredOptions"
:key="index"
:class="{ 'dropdown-item-selected': isSelected(item) }"
@mouseenter="highlightIndex = index"
@mouseleave="highlightIndex = -1"
@mousedown="onItemMouseDown(item)"
>
{{ item }}
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed, watch } from 'vue'
export default defineComponent({
name: 'Dropdown',
props: {
options: {
type: Array,
required: true,
},
value: {
type: [String, Array],
default: '',
},
multiple: {
type: Boolean,
default: false,
},
},
setup(props, { emit }) {
const inputValue = ref(props.value)
const showDropdown = ref(false)
const highlightIndex = ref(-1)
const filteredOptions = computed(() => {
const input = inputValue.value.trim().toLowerCase()
return props.options.filter((option) =>
option.toLowerCase().includes(input)
)
})
const isSelected = (item: string) => {
if (props.multiple) {
return (props.value as string[]).includes(item)
} else {
return props.value === item
}
}
const selectItem = (item: string) => {
if (props.multiple) {
const values = props.value as string[]
if (values.includes(item)) {
values.splice(values.indexOf(item), 1)
} else {
values.push(item)
}
emit('update:value', values)
} else {
emit('update:value', item)
showDropdown.value = false
}
}
const onInputBlur = () => {
showDropdown.value = false
}
const onEnterKeydown = () => {
if (highlightIndex.value >= 0) {
selectItem(filteredOptions.value[highlightIndex.value])
}
}
const onArrowDownKeydown = () => {
if (highlightIndex.value < filteredOptions.value.length - 1) {
highlightIndex.value++
}
}
const onArrowUpKeydown = () => {
if (highlightIndex.value > 0) {
highlightIndex.value--
}
}
const onMenuClick = () => {
if (highlightIndex.value >= 0) {
selectItem(filteredOptions.value[highlightIndex.value])
}
}
const onItemMouseDown = (item: string) => {
selectItem(item)
}
watch(
() => props.value,
(newValue) => {
inputValue.value = newValue
}
)
return {
inputValue,
showDropdown,
highlightIndex,
filteredOptions,
isSelected,
selectItem,
onInputBlur,
onEnterKeydown,
onArrowDownKeydown,
onArrowUpKeydown,
onMenuClick,
onItemMouseDown,
}
},
})
</script>
<style scoped>
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-input {
width: 100%;
padding: 6px 12px;
font-size: 14px;
line-height: 1.5;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
font-size: 14px;
text-align: left;
list-style: none;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
}
.dropdown-item {
display: block;
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.5;
color: #333;
white-space: nowrap;
}
.dropdown-item:hover,
.dropdown-item-selected {
color: #fff;
background-color: #337ab7;
}
.dropdown-item-selected {
font-weight: bold;
}
.dropdown-item:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.dropdown-item:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.dropdown-item:hover {
color: #333;
text-decoration: none;
background-color: #f5f5f5;
}
</style>
```
使用方法:
```html
<template>
<div>
<dropdown
:options="['Apple', 'Banana', 'Cherry', 'Durian']"
v-model="selectedFruits"
:multiple="true"
/>
<p>你选择了:{{ selectedFruits }}</p>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Dropdown from './Dropdown.vue'
export default defineComponent({
name: 'App',
components: {
Dropdown,
},
setup() {
const selectedFruits = ref<string[]>([])
return {
selectedFruits,
}
},
})
</script>
```
阅读全文