我有这个小的选择组件,当我单击按钮时,我需要获得一个下拉列表,但项目在按钮顶部打开而不是向下打开,并且前几个按钮没有显示我认为的所有下拉项目,因为有是一个溢出。我不太擅长只使用 css,因为大部分时间我都在使用 tailwind。
这是组件的代码:
模板:
<template>
<div class="select-wrapper" >
<div class="select-button" @click="() => (toggleList = !toggleList)">
<div class="select-button-text" :style="{ opacity: !!input ? 1 : 0.5 }">
{{ dislaySelected() ?? "Select Option" }}
</div>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
style="width: 20px; height: 20px;"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19.5 8.25l-7.5 7.5-7.5-7.5"
/>
</svg>
</div>
</div>
<div v-if="toggleList" class="select-droplist">
<input
v-if="options.length > 2"
v-model="searchQuery"
class="search-option"
placeholder="Search Options"
/>
<div
v-for="(option) in filteredOptions"
:key="option.id"
class="select-option"
@click="() => selectOption(option)"
>
<div :class="{ 'selected-option': isSelected(option) }">
{{ option.name }}
</div>
</div>
</div>
</div>
</template>
脚本:
<script setup lang="ts">
import { computed, ref, onMounted, } from "vue";
interface SelectOption {
id: string | number;
name: string
}
const props = withDefaults(defineProps<{
options: { id: string | number; name: string }[];
returnType?: keyof SelectOption;
modelValue?: string | number;
}>(), {
returnType: 'id'
});
const emits = defineEmits<{
"update:modelValue": [value: string | number];
}>();
const input = computed({
get: () => props.modelValue,
set: (value) => emits("update:modelValue", value),
});
const toggleList = ref<boolean>(false);
const searchQuery = ref<string>("");
const filteredOptions = computed(() =>
props.options?.filter((option) => option.name.match(searchQuery.value))
);
function selectOption(option: SelectOption) {
if (input.value === option[props.returnType]) {
input.value = null;
} else {
input.value = option[props.returnType];
toggleList.value = false;
}
}
function isSelected(option: SelectOption) {
return input.value === option[props.returnType];
}
function dislaySelected() {
return props.options?.find((option) => option[props.returnType] === input.value)?.name
}
onMounted(() => {
window.addEventListener("click", handleClickOutside);
});
function handleClickOutside(event: MouseEvent) {
const target = event.target as Element;
if (!target.closest(".select-wrapper")) {
toggleList.value = false;
}
}
</script>
风格:
<style>
.select-wrapper {
width: 100%;
height: 30px;
background-color: white;
border: 1px solid lightgray;
border-radius: 4px;
position: relative;
}
.select-button {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 1fr 46px;
place-items: center;
padding-left: 16px;
cursor: pointer;
}
.select-button-text {
width: 100%;
text-align: left;
}
.selected-option {
color: blue;
font-weight: bold;
}
.select-droplist {
width: 100%;
max-height: 300px;
background-color: white;
border: none;
border: 1px solid lightgray;
border-radius: 4px;
position: absolute;
bottom: 100%;
left: 0px;
overflow-y: auto;
z-index: 500;
}
.search-option {
width: 100%;
height: 46px;
padding: 0px 16px;
border: none;
border-bottom: 1px solid rgba(0 0 0 / 0.05) !important;
outline: none;
position: sticky;
top: 0px;
background-color: white;
}
.select-option {
width: 100%;
height: 46px;
display: flex !important;
align-items: center;
padding: 0px 16px;
border: none;
border-bottom: 1px solid rgba(0 0 0 / 0.05);
}
.select-option:hover {
background-color: rgba(0 0 0 / 0.05);
}
.select-option:nth-last-child(1) {
border-bottom: none;
}
</style>
据我所知,删除
bottom:100%
类下的 .select-droplist
就足够了。一切都应该正常工作。