vue3+elPlus 选择框select 下拉数据过千条,页面卡顿,分页解决
vue3+elPlus 选择框select 下拉数据过千条,页面卡顿,分页解决
注意:我这里是提前将下拉数据请求到,保存到本地,来分页
也可分页请求接口来获取,性质一样
最重要的是,监听滑动到底部的vue指令
v-loadmore=“selectListPageHandle”
在文件中directive—loadmore—index.tx
自定义指令
import { Directive, DirectiveBinding } from 'vue'
/**
* 操作权限处理
*/
export const loadmore: Directive = {
beforeMount(el: HTMLElement, binding: DirectiveBinding) {
let classDirect = el.className.split(" ")[1]
const selectDom = document.querySelector(`.event-select-poper${classDirect} .el-scrollbar__wrap`)
let loadMores = function () {
const isBase = this.scrollHeight - this.scrollTop <= this.clientHeight + 20
if (isBase) {
// 增加防抖
binding.value && binding.value()
}
}
// 将获取到的dom和函数挂载到el-select上,实例销毁时好处理
el.selectDomInfo = selectDom
el.selectLoadMore = loadMores
// 监听滚动事件
selectDom?.addEventListener('scroll', loadMores.bind(selectDom))
},
// 实例销毁
beforeUnmount(el) {
if (el.selectLoadMore) {
el.selectDomInfo.removeEventListener('scroll', el.selectLoadMore)
delete el.selectDomInfo
delete el.selectLoadMore
}
}
}
导入全局Index.ts
import { loadmore } from './loadmore'
import { App } from 'vue';
export default (app: App) => {
app.directive('loadmore', loadmore);
};
// 自定义指令
main.ts中引入(百度怎么引入全局指令,这里不详细说了)
import directive from '@/directive';
// 自定义指令
directive(app)
直接贴代码
// 封装的组件
<template>
<el-combo-box
:popper-class="'event-select-poper'+directCustom"
:class="directCustom"
v-loadmore="selectListPageHandle"
style="width: 100%"
v-model="valueName"
filterable
remote
:remote-method="remoteMethod"
:loading="loading"
:dropdown-visible-always="true"
:show-option-tooltip="true"
@focus="focusChange"
@change="selectChange"
>
<el-option
v-for="dict in selectList"
:key="dict.code"
:label="dict.label"
:value="dict.code"
>
</el-option>
</el-combo-box>
</template>
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
const props = defineProps({
modelValue: [String, Object, Array],
selectAllList: {
type: Array,
default: []
},
disabled: {
type: Boolean,
default: false
},
directCustom: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue', 'changeCallback'])
watch(
() => props.modelValue,
async (val) => {
if (val) {
// 回显默认值
valueName.value = val
} else {
valueName.value = []
}
}
)
const selectList = ref<any>([])
const valueName = ref('')
const loading = ref(false)
// 本地分页方法
let pageSize = 10
let pageNumber = 1
const resetselectListInit = () => {
pageNumber = 1 // 重置页数
selectList.value = [] // 重置选项
selectListPageHandle()
}
const selectListPageHandle = ($event) => {
if (loading.value) {
return false
}
// 数据加载完之后,不需要再获取
if (selectList.value.length >= props.selectAllList.length) {
return false
}
loading.value = true
let resData = props.selectAllList.slice((pageNumber - 1) * pageSize, pageNumber * pageSize)
selectList.value = selectList.value.concat(resData)
pageNumber += 1
//加载完成
loading.value = false
}
// 本地过滤
const remoteMethod = (query: string) => {
if (query) {
// 手动触发下拉框回滚至顶部,避免触发v-selectLazyLoad指令
// document.querySelector(`.el-select-dropdown__wrap`).scrollTop = 0;
if (loading.value) {
return false
}
loading.value = true
selectList.value = props.selectAllList.filter((item) => {
return item.codeAndName.toLowerCase().includes(query.toLowerCase())
})
loading.value = false
} else {
// 为空时,显示第一页数据
resetselectListInit()
}
}
const focusChange = () => {
// 重置(显示第一页数据)
resetselectListInit()
}
const selectChange = (data) => {
emit('update:modelValue', data)
emit('changeCallback', data)
}
</script>
<style scoped lang="scss"></style>
引用组件
import elComboxNew from ‘@/components/elComboxNew/index.vue’
<el-row>
<el-col :span="12" class="left-form-gen">
<el-form-item label="合同文本管理组织" prop="archivesDepartmentCode">
<elComboxNew
directCustom="archivesDepartmentCode"
v-model="dataForm.archivesDepartmentCode"
:selectAllList="archivesDepartmentCodeList"
></elComboxNew>
</el-form-item>
</el-col>
</el-row>
// 请求所有数据
onMounted(() => {
getArchivesDepartmentCodeList()
})
const archivesDepartmentCodeList = ref<any>([])
const getArchivesDepartmentCodeList = () => {
return new Promise((resolve, reject) => {
AJX_archivesDepartmentCodeList().then((res: any) => {
let archivesDepartmentCodeListStore = res.data ?? []
archivesDepartmentCodeList.value = archivesDepartmentCodeListStore.map((item) => {
return {
code: item.archivesDepartmentCode,
label: item.archivesDepartmentCode + item.archivesDepartmentName
}
})
resolve(true)
})
})
}