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 + 20if (isBase) {// 增加防抖binding.value && binding.value()}}// 将获取到的dom和函数挂载到el-select上,实例销毁时好处理el.selectDomInfo = selectDomel.selectLoadMore = loadMores// 监听滚动事件selectDom?.addEventListener('scroll', loadMores.bind(selectDom))},// 实例销毁beforeUnmount(el) {if (el.selectLoadMore) {el.selectDomInfo.removeEventListener('scroll', el.selectLoadMore)delete el.selectDomInfodelete 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"filterableremote:remote-method="remoteMethod":loading="loading":dropdown-visible-always="true":show-option-tooltip="true"@focus="focusChange"@change="selectChange"><el-optionv-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 = truelet 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 = trueselectList.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"><elComboxNewdirectCustom="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)})})
}