当下拉列表数据过大时,该如何应对?

栏目: JavaScript · 发布时间: 5年前

内容简介:在日常开发中,除了现成插件的使用外,还有很多问题是只能自己动手的。先抛出问题,当一个下拉列表的数据达到几千条甚至上万,这个时候浏览器已经会出现严重卡顿了。看看下面的例子如图所示,数据量达到这个问题其实和表格数据是同一个性能问题,表格的解决方式是通过分页器来减少页面承载的数据量。那么下拉列表该如何解决呢?通常我们都是一次性加载下拉的所有数据的,针对目前的难题,思路也是一样,采用分页来解决页面的性能问题。问题又来了,分页器是可以点击的,那下拉列表又不可以点击,那就只有在监听滚动事件里实现这件大事了。先来大纲:

在日常开发中,除了现成插件的使用外,还有很多问题是只能自己动手的。先抛出问题,当一个下拉列表的数据达到几千条甚至上万,这个时候浏览器已经会出现严重卡顿了。看看下面的例子

当下拉列表数据过大时,该如何应对?

如图所示,数据量达到 2W简单测试数据 (页面没有其他东西),点击加载下拉列表花了大概 5s 时间。出现这种情况心里真的是很复杂,这不是在玩我吗?

当下拉列表数据过大时,该如何应对?

解决思路

这个问题其实和表格数据是同一个性能问题,表格的解决方式是通过分页器来减少页面承载的数据量。那么下拉列表该如何解决呢?通常我们都是一次性加载下拉的所有数据的,针对目前的难题,思路也是一样,采用分页来解决页面的性能问题。问题又来了,分页器是可以点击的,那下拉列表又不可以点击,那就只有在监听滚动事件里实现这件大事了。先来大纲:

  1. 监听滚动
  2. 向下滚动时往后加载数据
  3. 向上滚动时往前加载数据
  4. 数据有进有出
    当下拉列表数据过大时,该如何应对?

好戏开始

监听滚动

<el-select class="remoteSelect" v-scroll v-model="value">
      <el-option :value="item.id" v-for="item in list" :key="item.id">{{item.name}}</el-option>
    </el-select>
复制代码

这里是基于vue与element-ui中 el-select 实现的监听滚动。这里是采用自定义指令的方式监听滚动

// directives目录下index.js文件

import Vue from 'vue'
export default () => {
  Vue.directive('scroll', {
    bind (el, binding) {
      // 获取滚动页面DOM
      let SCROLL_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
      SCROLL_DOM.addEventListener('scroll', function () {
        console.log('scrll')
      })
    }
  })
}
复制代码

在main.js中通过全局方法Vue.use()注册使用

import Directives from './directives'
Vue.use(Directives)
复制代码

这时滚动页面就可以看到控制的打印日志,代表监听已生效,接下来撸起袖子开干

当下拉列表数据过大时,该如何应对?

向下滚动时往后加载数据

首先要先判断出是向上滚动,还是向下滚动

  1. 记录上一次的滚动位置
  2. 当前位置与上一次的滚动位置作比较

通过一个公共变量来记录全局位置,通过 scrollTop 方法获取当前的滚动位置,并记录在公共变量 scrollPosition

bind (el, binding) {
      // 获取滚动页面DOM
      let SCROLL_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
      let scrollPosition = 0
      SCROLL_DOM.addEventListener('scroll', function () {
        // 当前的滚动位置 减去  上一次的滚动位置
        // 如果为true则代表向上滚动,false代表向下滚动
        let flagToDirection = this.scrollTop - scrollPosition > 0
        // 记录当前的滚动位置
        scrollPosition = this.scrollTop
        console.log(flagToDirection ? '滚动方向:下' : '滚动方向:上')
      })
    }
复制代码
当下拉列表数据过大时,该如何应对?

目前已知晓滚动的方向,接下来便根据滚动方向做相应的处理。将滚动行为告诉组件

...省略
        // 记录当前的滚动位置
        scrollPosition = this.scrollTop
        // 将滚动行为告诉组件
        binding.value(flagToDirection)
复制代码

事件接受在 v-scroll 指令中接受事件 v-scroll="handleScroll" ,在该方法 handleScroll 处理滚动行为。 接下来只需要在该事件中针对为向下的滚动发起请求数据即可

/*********************************
      ** Fn: handleScroll
      ** Intro: 处理滚动行为
      ** @params: param 为true代表向下滚动
      ** @params: param 为false代表向上滚动
    *********************************/
    handleScroll (param) {
      if (param) {
        // 请求下一页的数据
        this.list.push(...this.ajaxData(++this.pageIndex))
      }
    },
复制代码
当下拉列表数据过大时,该如何应对?

到这里滚动加载已经实现。只是加载太频繁了,如果快速滚动则会同时发出多个请求后台数据,在密集一些游览器中ajax就要开发并发排队了,可见并不理想。那如何控制呢?那换种方式触发 handleScroll 事件,在滚动位置距离滚动页面底部一定高度时在触发,例如距页面底部只有 100px 时触发 handleScroll 事件

scrollHeight
// 记录当前的滚动位置
        scrollPosition = this.scrollTop
        const LIMIT_BOTTOM = 100
        // 记录滚动位置距离底部的位置
        let scrollBottom = this.scrollHeight - (this.scrollTop + this.clientHeight) < LIMIT_BOTTOM
        // 如果已达到指定位置则触发
        if (scrollBottom) {
          // 将滚动行为告诉组件
          binding.value(flagToDirection)
        }
复制代码
当下拉列表数据过大时,该如何应对?

通过数据长度的变化可以知道触发事件已经明显和谐了很多,这种效果很手机懒加载的方式一样,数据会被不断的叠加。

小提示:会存在一个bug,即ajax是异步的,如果这个ajax请求花了 1s 才返回数据,而此时还在继续往下滚,那就会触发多个请求事件。如何避免这种情况呢? 答案是增加一个标志位,在请求前将该标志位设置为false,请求结束后设置为true。每次请求时先判断该标志位。如果为false则阻止该事件。

中场

再来看看我们的大纲

  1. 监听滚动
  2. 向下滚动时往后加载数据
  3. 向上滚动时往前加载数据
  4. 数据有进有出

到这里我们只完成①和②两个步骤。如果已经满足了你的需求,那你可以结束阅读了。如果对你有那么一点点帮助,先点个赞在离开。

前面说的都还只是基础操作,还没开始划重点呢。说好的无性能压力呢?

当下拉列表数据过大时,该如何应对?

先下班回家吃饭吧。周末继续写完


以上所述就是小编给大家介绍的《当下拉列表数据过大时,该如何应对?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

加密与解密(第4版)

加密与解密(第4版)

段钢 / 电子工业出版社 / 2018-10-1 / 198

《加密与解密(第4版)》以加密与解密为切入点,讲述了软件安全领域的基础知识和技能,如调试技能、逆向分析、加密保护、外壳开发、虚拟机设计等。这些知识彼此联系,读者在掌握这些内容之后,很容易就能在漏洞分析、安全编程、病毒分析、软件保护等领域进行扩展。从就业的角度来说,掌握加密与解密的相关技术,可以提高自身的竞争能力;从个人成长的角度来说,研究软件安全技术有助于掌握一些系统底层知识,是提升职业技能的重要......一起来看看 《加密与解密(第4版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具