开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第8天,点击查看活动详情
el-select是一种非常常用的form表单组件,比如常用的下拉选择,多选,远程搜索等,其中远程搜索很多时候由于搜索时数据太多,为了减轻服务端压力,会采用滑动分页查找的功能。
el-select远程搜索滑动分页
实现原理
el-select远程搜索滑动分页也就是说,接口根据输入框输入的内容进行查找,将内容按照分页进行返回。默认开始返回第一页数据(比如15条,20条甚至30条数据,可以自行决定)。然后滑动列表,当滑到底部的时候再请求接口,继续返回第二页数据,当滑到底部的时候再请求接口,继续返回第三页数据,依此类推,直至返回全部数据。
具体实现
1. 封装el-select组件
<template v-else-if="['autocomplete', 'autocompleteMultiple'].includes(item.type)">
<el-select
v-model="item.model"
filterable
remote
:multiple="item.type === 'autocompleteMultiple'"
:collapse-tags="item.type === 'autocompleteMultiple'"
:reserve-keyword="item.reserveKey"
popper-class="default-autocomplete"
:class="{ 'autocomplete': true, 'is-danger': item.validateObj ? item.validateObj.errorTip : false }"
:name="item.elemName"
:placeholder="item.placeholder"
:disabled="!!item.disabled"
:remote-method="item.remoteMethod"
:loading="item.loading"
@change="autoCompleteChange(key)"
@focus="autoCompleteFoucus(item)"
>
<el-option
v-for="(type) in item.values"
:key="type.itemKey"
:label="type.itemName"
:value="type.itemKey"
></el-option>
</el-select>
</template>
2. 远程搜索函数
2.1 定义下拉框选项列表fundCodeOpts,请求接口分页参数requsetObj,总数据条数totalRows,输入查询值searchKeyword。
const fundCodeOpts = reactive({
data: []
});
const requsetObj = reactive({
page: 1
});
const totalRows = ref(0);
const searchKeyword = ref('');
2.2 核心函数---请求函数
请求函数除了正常请求接口外,还实现了下列功能
- 判断是否是滑动到底部继续请求,如果是的话继续往fundCodeOpts后追加数据,否则需将fundCodeOpts重新置空
- 拿到数据之后判断当前fundCodeOpts是否是所有数据,如果是,将分页查询参数的页数置为1,去除监听函数,如果是需要找到当前下拉列表的元素(注意一定要是overflow: auto的可以滚动的元素),并为其绑定监听函数。
const editObj = reactive({
fundCode: {
name: 'fundCode',
text: '选择产品',
type: 'autocomplete',
model: '',
value: '',
clearable: true,
loading: loading,
reserveKey: false,
placeholder: '请输入基金代码或名称',
values: fundCodeOpts.data,
validateObj: {
errorTip: '',
required: true,
ifRequiredFill: false
},
remoteMethod: (query, addFlag = false) => {
loading.value = true;
if (!addFlag) {
fundCodeOpts.data = [];
}
const url = globObj.$api.fundSearch;
if (query === undefined) return;
searchKeyword.value = query;
globObj.$axios.get(url, {
params: {
pageNum: requsetObj.page,
pageSize: 20,
query: query,
}
}).then((res) => {
let arr = res.data.res.list || [];
totalRows.value = res.data.res.totalRows;
loading.value = false;
arr.forEach((item) => {
fundCodeOpts.data.push({
itemKey: item.fundCode,
itemName: item.fundName
});
});
})
.catch((err) => {
loading.value = false;
console.log(err);
})
.finally(() => {
if (fundCodeOpts.data && fundCodeOpts.data.length < totalRows.value) {
const parentDom = document.querySelector('.el-select-dropdown.default-autocomplete').querySelectorAll('.el-select-dropdown__wrap.el-scrollbar__wrap.el-scrollbar__wrap--hidden-default');
parentDom.forEach((e, idx) => {
if ( e.querySelector('.el-select-dropdown__list') ) {
dom.value = parentDom[idx];
dom.value.addEventListener(
'scroll',
scrollAddEventFn,
true
);
}
});
} else {
requsetObj.page = 1;
dom.value?.removeEventListener('scroll', scrollAddEventFn, true);
}
editForm.value.changeEditModelVal(
'fundCode',
'values',
fundCodeOpts.data
);
});
}
},
holdAmount: {
name: 'holdAmount',
text: '持有金额',
type: 'input',
model: '',
value: '',
unitModel: '1',
clearable: true,
moreUnit: true,
placeholder: '请输入',
validateObj: {
errorTip: '',
required: true,
ifRequiredFill: false,
regExp: [
{
err: '只能输入整数或小数(保留两位小数)',
reg: '^(?!(0[0-9]{0,}$))[0-9]{0,}[.]{0,}[0-9]{1,2}$',
},
],
},
moreValues: [
{
itemKey: '1',
itemName: '元'
},
{
itemKey: '2',
itemName: '万元'
}
]
},
holdIncome: {
name: 'holdIncome',
text: '持有收益',
type: 'input',
model: '',
value: '',
unitModel: '1',
clearable: true,
moreUnit: true,
placeholder: '请输入',
validateObj: {
errorTip: '',
required: true,
ifRequiredFill: false,
regExp: [
{
err: '只能输入整数或小数(保留两位小数)',
reg: '^(?!(0[0-9]{0,}$))[0-9]{0,}[.]{0,}[0-9]{1,2}$',
},
],
},
moreValues: [
{
itemKey: '1',
itemName: '元'
},
{
itemKey: '2',
itemName: '万元'
}
]
}
});
2.3 实现滑动监听函数
当滑动到列表底部时,将分页参数的页数+1,然后请求接口。
const scrollAddEventFn = (e) => {
const self = e.target;
if (self.scrollHeight - self.scrollTop <= self.clientHeight) {
requsetObj.page++
editObj.fundCode.remoteMethod(searchKeyword.value, true);
}
};
实现效果
滑动下拉框可以加载更多数据