需求背景
常见的需求中经常有下拉框作为搜索的条件之一,我们需要先调接口拉取数据供用户进行选择。当遇到数据量大,或考虑到随着时间推移,数据量会变得庞大的情况,通常接口会采取分页设计。
最佳实践
- 默认先只拉取第一页数据,供用户选择
- 当用户滚动至数据末尾,拉取下一页数据(数据懒加载)
- 支持关键词搜索
- 支持一键清空
实现细节
Vue项目我们团队基本上统一使用Element UI / Element Plus,本次针对 Element Plus的Select组件实现了公共方法 – 自定义指令完成懒加载。(Vue 3适用)
使用
// 引入
import vLoadMore from "@/utils/loadMore"
// 绑定指令
<el-select v-load-more="loadMoreData"></el-select>
原理
基于Element Plus Select组件滚动区域,监听滚动是否到达底部
懒加载逻辑
当元素内容的总高度 – 已滚动的高度 <= 元素的可见区域高度,代表当前滚动位置已经接近或到达底部,此时调用父组件传入回调方法即可。
初始状态
滚动到底部
Element Plus Select组件滚动区域选择
当页面中只用到一个下拉框,你可以直接使用类名定位。
当页面中有多个下拉框,上面的方法会导致数据错乱。查看Select DOM可以发现,不同的下拉框记录了不同的control id
而control id可以定位到对应的下拉框。举例:平台选择器的control id是”el-id-6389-3″,对应的下拉框DOM id也是”el-id-6389-3″
因此,我们可以利用以上属性定位到Select组件的实际滚动区域。
代码
/* Element Plus
Select组件 自定义指令-触底加载更多
使用:
1. 页面中引入
```
import vLoadMore from "@/utils/loadMore"
```
2. 绑定自定义指令
```
<el-select v-load-more="loadMoreData"></el-select>
```
*/
const vLoadMore = {
mounted(el, binding) {
const child = el.querySelector('.el-select__input')
const id = child.getAttribute('aria-controls')
const popper = document.getElementById(id)
const SELECT_DOM = popper.parentElement
SELECT_DOM.addEventListener('scroll', function () {
const CONDITION = this.scrollHeight - this.scrollTop <= this.clientHeight
if (CONDITION) {
binding.value()
}
})
}
}
export default vLoadMore