element 提供了 el-select组件,并且支持远程搜索,但是对于数据量大需要翻页的场景并未提供相应配置,所以自己写了一个通用组件,作为记录

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

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

<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
remote
remote-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的场景,组件完整代码已经上传至github,文件添加到项目可以直接调用。

地址:https://github.com/LearnerPing/SelectCommon.git

如果你觉得还算好用,请在github上面给我点个star

Vue3+Ts笔记:基于element-UI 实现下拉框滚动翻页查询通用组件的更多相关文章

  1. Vue+Element UI一个下拉框传字典值和对应字典Label

    <el-select @change="getDeptName" v-model="form.deptCode"> <el-option v- ...

  2. vue开发 element的select下拉框设定初值后,不能重新选择的问题

    问题描述: 用的element的select可多选的下拉选框,在回显后有初始值的情况下,不能修改,也不能再选择 如图,明明点击了一般内勤主管,但没有任何反应 <el-select v-model ...

  3. js基于json的级联下拉框

    级联下拉列表是项目中常用到的.比如省市县,比如企业性质等,做成一个js通用组件, 在静态页出来后可以直接插入,将数据和html静态页做一个解耦. 贴出来抛砖引玉吧. /** * @author sun ...

  4. 基于bootstrap-multiselect.js的下拉框联动

    背景:当option特别多时,一般的下拉框选择起来就有点力不从心了,所以使用multiselect是个很好的选择,可以通过输入文字来选择选项很方便,但是有一个需要下拉框联动,网上找了半天才找到解决方法 ...

  5. 【WPF学习笔记】之如何设置下拉框读取SqlServer数据库的值:动画系列之(一)

    先前条件:设置好数据库,需要三个文件CommandInfo.cs.DbHelperSQL.cs.myHelper.cs,需要修改命名空间,参照之前随笔http://www.cnblogs.com/Ow ...

  6. 关于Vue+iview的简单下拉框滚动加载

    话不多说,直接上代码,作用是下拉框内容无限滚动加载: Html: <FormItem style="position:relative" label="用户名:&q ...

  7. Bootstrap 学习笔记2 栅格系统 辅助类下拉框

    辅助类和响应式工具: 颜色和字体相同 响应式工具: 图标菜单按钮组件: btn-group 按钮式下拉菜单

  8. javaFX笔记----ComboBox模仿qq账号下拉框删除账号

    myComboBox.setCellFactory( new Callback<ListView<String>, ListCell<String>>() { @O ...

  9. bootstrap下拉框式标签页

    <ul id="myTab" class="nav nav-tabs"> <li class="active"> & ...

  10. 基于Bootstrap的下拉框插件bootstrap-select

    写在前面: 在这次的项目中,没有再使用liger-ui做为前端框架了,改为了Bootstrap,这次也好接触下新的技术,在学习的过程中发现,Bootstrap的一些组件基本都是采用class的形式,就 ...

随机推荐

  1. go语言实现终端里的倒计时

    最近在更新系统的时候发现pacman的命令行界面变了,我有很久没更新过设备上的Linux系统了,所以啥时候变的不好说.但这一变化成功勾起了我的好奇心.新版的更新进度界面如下: 新的更新进度界面能同时显 ...

  2. 【Python&Hypermesh】ABAQUS导入网格,并在Part内保留SET

    在Hypermesh定义好set,划分好网格以后,可以导出为INP.然后在ABAQUS导入inp,就可以得到网格.但是这样倒进来的网格一般有两个问题: 网格全在一个部件里,原来定义好的Set会出现在装 ...

  3. 【ABAQUS文档笔记】ABAQUS刚体单元和可变形单元的review

    学习笔记,帮助文档学习笔记 目录 A. finite element DOF of Elem Order of Elem Formulation of Elem Integration A.1 con ...

  4. ascci 码表

  5. DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

    大家好,我是狂师. 前阵子在知乎闲逛时,有个问题激起了大家的热议:"DeepSeek 如何颠覆传统软件测试?测试工程师会被淘汰吗".这看似简单的一问,激起层层思考,针对这个问题,今 ...

  6. Grafana导入 json 文件的 dashboard 错误 Templating Failed to upgrade legacy queries Datasource xxx not found

    前言 编辑或者修改后的 dashboard 保存为 json 文件,在其他环境导入使用,报错 Failed to upgrade legacy queries Datasource xxxxxxx w ...

  7. 关于DevExpress VCL汉化方法

    用法1:在工程中加入控件cxLocalizer; 在程序中加入如下语句: Localizer.LoadFromFile('DevLocal.ini'); Localizer.Language := ' ...

  8. 深入理解Hadoop读书笔记-3

    背景 公司的物流业务系统目前实现了使用storm集群进行过门事件的实时计算处理,但是还有一个需求,我们需要存储每个标签上传的每条明细数据,然后进行定期的标签报表统计,这个是目前的实时计算框架无法满足的 ...

  9. study PostgreSQL【2-FireDAC连接PostgreSQL】

    就这么个简单问题,一下午时间.想想就憋屈. 那么牛逼哄哄FireDAC居然连接PostgreSQL出问题了.帮助中说的啥意思,咱也不明白.网上一通也是云里雾里. 上干货,具体点: TFDConnect ...

  10. spring cloud alibaba的小坑:Caused by: com.alibaba.nacos.api.exception.NacosException: endpoint is blank报错问题,

    一.是因为加添spring cloud alibaba配置中心依赖和bootstrap.xml又不使用的问题