Vue 3 组件导致溢出

问题描述 投票:0回答:1

我有这个小的选择组件,当我单击按钮时,我需要获得一个下拉列表,但项目在按钮顶部打开而不是向下打开,并且前几个按钮没有显示我认为的所有下拉项目,因为有是一个溢出。我不太擅长只使用 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>
css vuejs3 buffer-overflow
1个回答
0
投票

据我所知,删除

bottom:100%
类下的
.select-droplist
就足够了。一切都应该正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.