• el-select数据过多的解决(纯前端)


    前言

    el-select数据过多这个问题应该很多人都遇到过,在生产环境中数据几百、几千条是比较常见的。当数据过多时,就会造成浏览器卡顿,如果客户电脑性能不行,浏览器直接卡死也有可能。

    解决

    先说一下现在项目中遇到的两种解决方案:

    原解决方案

    添加分页条

    这种方案好像有点问题,具体什么问题忘记了,感兴趣的可以看一下:element ui 下拉框分页(下拉框数据过多)

    在这里插入图片描述
    滚动懒加载

    这种方式是我的一个同事写的,代码就不放了。原理就是一开始加载20条数据,当列表滚动到底部的时候,加载下一个20条数据。

    先解决方案

    最近在思考,卡顿的根本原因就是数据太多了。那么我能否一下子把所有数据都请求过来,但是我每次就显示20条数据,当我向下滚动时我就渲染下一个20条数据。

    当然有一些问题是需要解决的:

    • 数据回显的问题。当下拉绑定的值在下拉项里匹配不到时就是显示绑定的值,而不是对应的名称。目前考虑:这20条数据里如果有这个值则不处理;没有这个值,则往数组里添加上。这样会有20条数据和21条数据两种情况
    • 模糊搜索的话,也是每次显示20条数据
    • 数据切换的话打算通过鼠标滑轮事件来实现

    示例

    肯定会有些问题,但是作为一个demo就懒得处理了,纯粹是提供一种思路

    在这里插入图片描述

    <template>
        <div>
            <el-select v-model="selectValue" placeholder="Select" size="large" :loading="loading" filterable
                -change="handleVisible" :filter-method="myFilter">
                <el-option v-for="item in showOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
        </div>
    </template>
    
    <script lang="ts" setup>
    import { ref, onMounted, nextTick } from "vue";
    
    // 绑定的值
    const selectValue = ref(22);
    // 下拉显示的值
    const showOptions = ref<Array<any>>([])
    // 下拉所有的值
    const allOptions = ref<Array<any>>([])
    // 每次显示的条数
    const showCount = 20
    // 当前页
    const current = ref(1)
    // 总页数
    const total = ref(0)
    // loading动画
    const loading = ref(false)
    // 外层容器
    const outer = ref()
    // 上一次滚动的值
    const lastScrollTop = ref(0)
    // 用于记录中间值
    const tempList = ref<Array<any>>([])
    
    onMounted(() => {
        // 假设下拉值共用100条数据
        for (let i = 1; i <= 200; i++) {
            allOptions.value.push({
                value: i,
                label: 'Item ' + i
            })
        }
        tempList.value = allOptions.value
        // 计算总页数
        total.value = Math.ceil(200 / showCount)
        updateShowOptions()
    })
    
    // 更新下拉显示的值
    const updateShowOptions = () => {
        const startIndex = (current.value - 1) * showCount
        showOptions.value = tempList.value.slice(startIndex, startIndex + showCount);
        // 处理一下绑定值的回显
        handleBindValue()
    }
    
    
    // 判断当前绑定值是否在下拉里
    const handleBindValue = () => {
        // 有绑定值但是绑定值不在下拉里
        if (selectValue.value && !showOptions.value.find(e => e.value == selectValue.value)) {
            // 找到该值对应的下拉
            let item = allOptions.value.find(e => e.value == selectValue.value)
            showOptions.value.push(item)
        }
    }
    
    // 自定义搜索
    const myFilter = (val) => {
        // 这一块应该也是固定显示20条数据,但是没想好怎么处理,并且筛选后的数据也会少一些
        // console.log("搜索:", val)
        tempList.value = allOptions.value.filter(e => e.label.includes(val))
        // 重置当前页
        current.value = 1
        // 更新总条数
        total.value = Math.ceil(tempList.value.length / showCount)
        updateShowOptions()
    }
    
    // 下拉框显示处理
    const handleVisible = (val) => {
        console.log("显示了:", val)
        if (val) {
            // 记录向下滚动的上一次值
            lastScrollTop.value = 0;
            nextTick(() => {
                const out = document.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
                outer.value = out
                console.log(out, out.clientHeight)
                const inner = document.querySelector('ul.el-scrollbar__view')
                console.log(inner, inner.clientHeight)
                if (inner.clientHeight > out.clientHeight) {
                    // 说明存在滚动条,可以滚动,添加滑轮滚动事件
                    outer.value?.addEventListener('wheel', handleWeel)
                }
            })
        } else {
            // 重置下拉项
            current.value = 1
            // 更新总条数
            total.value = Math.ceil(tempList.value.length / showCount)
            tempList.value = allOptions.value
        }
    }
    
    // 滚动事件
    const handleWeel = event => {
        if (event.deltaY > 0) {
            //   console.log('向下滚动', out.scrollTop);
            if (lastScrollTop.value != outer.value.scrollTop) {
                // 说明还能往下滚
                lastScrollTop.value = outer.value.scrollTop
            } else {
                // 当不变时,说明滚动底部了,显示下一页的值
                if (lastScrollTop.value == outer.value.scrollTop && current.value < total.value) {
                    current.value += 1
                    console.log("滚动到底部了显示下一页")
                    loading.value = true
                    // 滚动条滚回顶部
                    outer.value.scrollTop = 10
                    setTimeout(() => {
                        loading.value = false
                    }, 500)
                }
            }
        } else if (event.deltaY < 0) {
            if (outer.value.scrollTop == 0 && current.value > 1) {
                // 滚动到0说明到头了,显示上一页的数据
                current.value -= 1;
                console.log("滚动到头了加载上一页")
                loading.value = true
                // 滚动条滚回顶部
                outer.value.scrollTop = 10
                setTimeout(() => {
                    loading.value = false
                }, 500)
            }
        }
        // 更新显示的值
        updateShowOptions()
    }
    
    </script>
    
    <style lang="scss" scoped></style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
  • 相关阅读:
    以功促防 攻防演练对企业价值-全面提升企业安全性
    vue2循环的列表商品选择后的商品禁用
    C# 在流行度指数上将超过Java
    JavaScript中Set的基本指南
    Java API 类导入
    使用nodejs/exceljs读取、操作、写入excel文件
    deadmau5 《光之塔》 NFT 系列来袭!
    MySQL8.0优化 - 锁 - 从数据操作的类型划分:读锁、写锁
    了解交互设计:深入研究五个重要维度
    薪资17K+需要什么水平?98年测试工程师面试实录…
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/132690643