当前位置: 首页 > ops >正文

基于element-UI 实现下拉框滚动翻页查询通用组件

初始化控件,定义传入参数

将远程查询的接口封装为函数,作为参数传入组件,可以适应多种场景

<script lang="ts" setup>
import { nextTick, onMounted, ref, watch } from 'vue';
import { message } from "@/utils/message";interface FetchParams {//远程搜索使用的参数[key: string]: any;
}const props = defineProps({fetchData: {//传入进行查询的接口type: Function,required: true},modelValue: {//select 组件绑定的值type: [String, Number],default: ''},name: {//下拉框无对应选项的时候用于填充到选项里的值type: String,default: ''},placeholder: String,disabled: Boolean,param: {//查询接口调用的参数type: Object,default: () => ({})}
});

调用传入函数获取远程数据

对传入函数的基本调用以及一些异常处理,loading的值是el-select的配置项,这里需要注意的是在配置了loading = true时,刷新下拉框会内容时会明显看到选项闪烁一下,如果不希望展示搜索刷新的效果,就不要配置loading

const getData = async (params: FetchParams, isLoadMore = false) => {if (!hasMore.value && isLoadMore) return;loading.value = true;try {const res = await props.fetchData(params);if (!res.error) {const newItems = res.items?.map(item => ({label: item.name,value: item.id})) || [];if (isLoadMore) {// 加载更多时,追加数据itemList.value = [...itemList.value, ...newItems];} else {// 首次加载或搜索时,替换数据itemList.value = newItems;}// 如果有 name 值,确保它在列表中if (props.name && value.value) {const existingItem = itemList.value.find(item => item.value === value.value);if (!existingItem) {itemList.value = [{label: props.name,value: value.value}, ...itemList.value];}}// 判断是否还有更多数据hasMore.value = newItems.length === params.MaxResultCount;totalItems.value = itemList.value.length;} else {// 如果接口返回错误,清空数据itemList.value = [];hasMore.value = false;totalItems.value = 0;}} catch (error) {// 如果发生错误,清空数据itemList.value = [];hasMore.value = false;totalItems.value = 0;message(error, { customClass: 'el', type: 'error' });} finally {loading.value = false;}
};

远程搜索方法

// 远程搜索方法
const remoteSearch = debounce(async (query: string) => {currentPage.value = 1; // 重置页码hasMore.value = true; // 重置加载更多状态if (query) {const params: FetchParams = {...props.param,skipCount: 1,MaxResultCount: 10,keyword: query};await getData(params);} else {// 如果搜索词为空,则加载初始数据const params: FetchParams = {...props.param,skipCount: 1,MaxResultCount: 10};await getData(params);}
}, 300);

下拉滚动事件监听

这里就是最坑的地方了,因为el-select组件被封装过,所以@scroll.native不会有任何效果。为了实现下拉框的滚动加载功能,只能用@visible-change 来监听下拉框,并在下拉框状态变化的时候添加下拉滚动事件

const handleVisibleChange = async (visible) => {if (visible) {// 先清空数据itemList.value = [];totalItems.value = 0;hasMore.value = true;currentPage.value = 1;// 加载初始数据const params: FetchParams = {...props.param,skipCount: 1,MaxResultCount: 10};await getData(params);// 添加滚动事件监听const dropdown = document.querySelector('.myselect-loadmore .el-select-dropdown__wrap');if (dropdown) {dropdown.addEventListener('scroll', handleScroll);// 重置滚动位置dropdown.scrollTop = 0;}} else {// 移除滚动事件监听const dropdown = document.querySelector('.el-select-dropdown');if (dropdown) {dropdown.removeEventListener('scroll', handleScroll);}}
};//防抖函数
function debounce<T extends (...args: any[]) => any>(func: T, delay: number) {let timeout: NodeJS.Timeout;return function (this: any, ...args: Parameters<T>) {const context = this;clearTimeout(timeout);timeout = setTimeout(() => func.apply(context, args), delay);};
}const handleScroll = debounce(async (event) => {// 判断是否滚动到底部const bottom = event.target.scrollHeight === event.target.scrollTop + event.target.clientHeight;if (bottom && !loading.value && hasMore.value) {currentPage.value++;// 调用父组件传递的函数,并传入子组件的参数const params: FetchParams = {...props.param,skipCount: currentPage.value,MaxResultCount: 10};await getData(params, true);}
}, 100);

el-select 组件配置

popper-class的设置是为了让事件能够准确绑定到下拉框,不添加该属性可能导致事件被绑定到父组件上面

<template><el-select v-model="value" class="myselect" :placeholder="placeholder || '请选择!'" popper-class="myselect-loadmore"filterable remoteremote-show-suffix:remote-method="remoteSearch"clearable :disabled="disabled" @visible-change="handleVisibleChange"@update:modelValue="(val) => emit('update:modelValue', val)"><el-option v-for="(item, index) in itemList" :key="item.value" :label="item.label" :value="item.value" /></el-select>
</template>

父组件调用示例

              <SelectCommon v-model="Id" :fetch-data="getList" :param="selectParams"placeholder="请选择" />

适用于Vue3+ts+element的场景,文件添加到项目可以直接调用。

http://www.xdnf.cn/news/10096.html

相关文章:

  • 软件需求文档如何做精确度度量
  • write和read命令中的通道号指南
  • GRCh38版本染色体位置转换GRCh37(hg19)
  • 【leetcode】704. 二分查找
  • Java 基础 常见知识
  • 如何科学测量系统的最高QPS?
  • 深入理解 Git 底层机制:指针(Refs)、提交(Commit)与分支的关系
  • Re--题
  • 轻量级swiper插件推荐
  • 在线制作幼教早教行业自适应网站教程
  • TDengine 运维——巡检工具(定期检查)
  • AD9361 的工作原理
  • 正点原子Z15I ZYNQ 开发板发布!板载PCIe2.0、SPFx2、MIPI CSI等接口,资料丰富!
  • kanass V1.1.3版本发布,支持需求评审和Jira的数据导入
  • cocosCreator导出的web工程加载本地图片
  • 默克微生物培养基选择指南
  • Linux 创建用户
  • 4.0/Q2,GBD数据库最新文章解读
  • Oracle数据类型AnyType与AnyData
  • 4.Haproxy搭建Web群集
  • 【Golang进阶】第六章:包管理与工程实践——从模块化开发到CI/CD全流程
  • 沉浸式 “飞进” 鸟巢:虚拟旅游新体验​
  • 发布订阅者模式
  • stm32无刷电机控制_滑膜观测器更改电机如何调整?
  • 《java创世手记》---java基础篇(下)
  • 招工招聘系统开发——适配多元场景,满足企业多样化招聘需求
  • 91.评论日记
  • 2025年文学与文化发展国际会议(ICLCD 2025)
  • FEMFAT许可分析的数据可视化方法
  • 重读《人件》Peopleware -(13)Ⅱ 办公环境 Ⅵ 电话