vue3+elPlus 选择框select 下拉数据过千条,页面卡顿,分页解决

vue3+elPlus 选择框select 下拉数据过千条,页面卡顿,分页解决

注意:我这里是提前将下拉数据请求到,保存到本地,来分页

也可分页请求接口来获取,性质一样

最重要的是,监听滑动到底部的vue指令

v-loadmore="selectListPageHandle"

在文件中directive---loadmore---index.tx

自定义指令

javascript 复制代码
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

javascript 复制代码
import { loadmore } from './loadmore'
import { App } from 'vue';
export default (app: App) => {

  app.directive('loadmore', loadmore);

};

// 自定义指令

main.ts中引入(百度怎么引入全局指令,这里不详细说了)

javascript 复制代码
import directive from '@/directive';
// 自定义指令
directive(app)

直接贴代码

javascript 复制代码
// 封装的组件
<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'

javascript 复制代码
<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)
    })
  })
}
相关推荐
_Kayo_25 分钟前
JS深拷贝 浅拷贝、CSS垂直水平居中
开发语言·前端·javascript
碎像1 小时前
uni-app实战教程 从0到1开发 画图软件 (学会画图)
前端·javascript·css·程序人生·uni-app
Hilaku1 小时前
从“高级”到“资深”,我卡了两年和我的思考
前端·javascript·面试
WebInfra2 小时前
Rsdoctor 1.2 发布:打包产物体积一目了然
前端·javascript·github
兮漫天2 小时前
bun + vite7 的结合,孕育的 Robot Admin 【靓仔出道】(十一)
前端·vue.js
秋天的一阵风2 小时前
😈 藏在对象里的 “无限套娃”?教你一眼识破循环引用诡计!
前端·javascript·面试
用户1409508112802 小时前
原型链、闭包、事件循环等概念,通过手写代码题验证理解深度
前端·javascript
汪子熙2 小时前
错误消息 Could not find Nx modules in this workspace 的解决办法
前端·javascript
前端美少女战士2 小时前
post方法下载文件,需做哪些特殊处理
javascript·react.js
前端开发爱好者2 小时前
Vite 7.1.1 疑似遭受大规模 "攻击"!
前端·vue.js·vite