Vue3+elementUI-plus réalise le défilement virtuel de la liste déroulante sélectionnée

J'ai vérifié plusieurs solutions sur Internet, soit elles sont incompatibles, soit elles ne supportent pas vue3. J'en ai
enfin trouvé une adaptée, et elle a été utilisée en ligne. Je dois modifier le style :
le code est le suivant :
cité dans main.js

import 'vue3-virtual-scroller/dist/vue3-virtual-scroller.css';
import {
    
     RecycleScroller } from 'vue3-virtual-scroller';
app.component('RecycleScroller', RecycleScroller);

déclaration de vue :

<el-form-item label="用户" prop="seriesId">
                    <div ref="selectWrapper" @click="toggleDropdown($event)" class="select-wrapper">
                        <el-input style="width: 240px"
                        placeholder="请输入搜索内容"
                        v-model="selectedOption"
                        :suffix-icon="selectedOption ? 'el-icon-circle-close' : null"
                        @clear="clearSearch"
                        ></el-input>
                    </div>
                    <el-icon class="clear-btn" v-if="selectedOption" @click.stop="clearSearch"><CircleClose /></el-icon>
                    <Teleport to="body">
                        <div v-show="isOpen"  ref="dropdown" class="virtual-dropdown" :style="dropdownStyles" @click="closeDropdown">
                            <RecycleScroller
                                class="virtual-list"
                                :buffer="1000"
                                :prerender="200"
                                style="height: 270px"
                                :item-size="24"
                                key-field="id"
                                :items="filteredSeriesList"
                                >
                                <template v-slot="{ item, index }">
                                    <div class="list-item" :key="index" @click.stop="handleItemClick(item)">
                                    <span>{
    
    {
    
     item.id }}</span>&nbsp;-&nbsp;
                                    <span>{
    
    {
    
     item.name }}</span>
                                    </div>
                                </template>
                                </RecycleScroller>
                        </div>
                    </Teleport>
                </el-form-item>

code js :

<script setup name="LeadsList">
const rowCount = ref(0);
    const rowCount2 = ref(0);
    const leadsList = ref([]);
    const loading = ref(false);
    const activeButton = ref(0);
    const seriesList = ref([]);
    const filteredSeriesList = ref([]); // 初始状态下,筛选后的列表与原始列表相同
    const indexLayer = ref(false);
    const open = ref(false);
    const dropdown = ref(null);
    const repeatLoading = ref(false);
    const repeatList = ref([]);
    const dropdownStyles = ref({
    
    });
    const selectWrapper = ref({
    
    });
    const isOpen = ref(false);
    const selectedOption = ref('');
    const data = reactive({
    
    
        queryParams: {
    
    
            pageIndex: 1,
            pageSize: 10,
            phone: "",
            seriesId: null,
        },
        queryParamsRepeat: {
    
    
            pageIndex: 1,
            pageSize: 10,
            companyId: 1,
            userId: 1
        }
    });

    const {
    
     queryParams,queryParamsRepeat } = toRefs(data);


    watch(selectedOption, (newValue) => {
    
    
        search(newValue);
    });
    function search (keyword) {
    
    
        if (keyword.trim() === "") {
    
    
      filteredSeriesList.value = [...seriesList.value];
        } else {
    
    
        filteredSeriesList.value = seriesList.value.filter((item) =>
            item.name.toLowerCase().includes(keyword.toLowerCase())
        );
        }
    }
    function handleItemClick(item) {
    
    
      queryParams.value.seriesId = item.id;
      selectedOption.value = item.name;
      closeDropdown()
    }
    function closeDropdown(event = null) {
    
    
        isOpen.value = false;
        if (
            event &&
            (selectWrapper.value.contains(event.target) ||
            dropdown.value.contains(event.target))
        ) {
    
    
            return;
        }
        isOpen.value = false;
    }
    function toggleDropdown($event) {
    
    
        $event.stopPropagation(); // 阻止事件冒泡
        isOpen.value = !isOpen.value;
        if (isOpen.value) {
    
    
            const rect = selectWrapper.value.getBoundingClientRect();
            const {
    
     x, y, width, height } = rect;
            dropdownStyles.value = {
    
    
            position: 'fixed',
            top: `${
     
     y + height}px`,
            left: `${
     
     x}px`,
            width: `${
     
     width}px`,
            };
        }
    }
    function clearSearch () {
    
    
        queryParams.value.seriesId = '';
        selectedOption.value = '';
        filteredSeriesList.value = [...seriesList.value];
    }

code css :

.virtual-dropdown {
    
    
  position: absolute;
  inset: 100% auto auto 0;
  z-index: 2000;
  width: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.list-item {
    
    
  display: flex;
  padding: 0 10px;
  align-items: center;
  height: 24px;
  cursor: pointer;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

.list-item:hover {
    
    
  background-color: #f5f7fa;
}
.clear-btn {
    
    
    border: none;
    background: transparent;
    cursor: pointer;
    position: absolute;
    right: 14px;
  }

Guess you like

Origin blog.csdn.net/xingchen678/article/details/132284691