el-cascader级联选择器数据过多分页显示

 

业务场景:一级二级数据量不多 ,一次返回,第三级数据点击二级时请求 ,第一级选项不可选,第三级选项加载出来的情况下第二级选项才能全选

问题:实现过程中发现三级数据量过多(8千多条)会造成浏览器卡死

解决:三级选项分页显示

欢迎各位小伙伴评论区多多指教 (有时间会优化,整理demo出来)

主要代码

html

<el-cascader
  v-model="tagsFocus"
  :options="options"
  :props="propsTag"
  filterable
  collapse-tags
  placeholder="请选择"
  @expand-change="nodeChange"
  @change="blurData"
/>

js

1.在nodeChange中判断是否是第二级选项 去请求数据

2.getLevel3Data请求处理数据

3.监听滚动事件 scrollCallback

nodeChange(val) { 
  // cascaderScroll 用来记录滚动数据 page:第几页 data要滚动的三级选项全部数据
  this.cascaderScroll.page = null
  this.cascaderScroll.data = []
  // 解除绑定的滚动事件
  if (this.currentScroll) {
    this.currentScroll.removeEventListener('scroll', this.eventListenerScroll(this.currentScroll))
  }
// 判断点击的是第二级选项 请求数据
  if (val.length === 2) {
    this.getLevel3Data(val[1])
  }
},
async getLevel3Data(obj, node) {
  const data = {
    topics: obj.topics,
    tagType: obj.name
  }
  try {
    // node.loading = true
    const res = await searchTag(data)
    let addData = res.data
    this.cascaderScroll.isScroll = false
    this.cascaderScroll.tagName = obj.name
    this.cascaderScroll.pName = obj.topics
        //如果数据超过2000条才开始分页
    if (addData.length > 2000) {
      this.cascaderScroll.isScroll = true
      this.cascaderScroll.data = [...addData]
      this.cascaderScroll.page = {
        total: this.cascaderScroll.data.length,
        totalPage: Math.ceil(this.cascaderScroll.data.length / 10),
        size: 10,//一页10条数据
        index: 0
      }
      addData = addData.slice(0, 10)
    }

    // 将数据添加到options 
    this.addOptionData(addData)

    const _this = this
    //
    if (this.cascaderScroll.isScroll) { // 滚动的 要禁止全选
     
      setTimeout(() => {
        document.querySelectorAll('.tags .el-scrollbar:nth-child(2) .el-checkbox').forEach(el => {
          var span = el.nextSibling
          if (span.innerText === obj.name) {
            var input = el.querySelectorAll('input')
            console.log(span.innerText + '-----------------' + obj.name, input[0])
            input[0].setAttribute('disabled', true)
            el.onclick = () => {
              _this.$message.info('当前标签不可全选!')
            }
          }
        })
      }, 500)
      // 监听滚动事件
      setTimeout(() => {
        this.scrollCallback()
      }, 1000)
    }
  } catch (e) {
    console.info(e)
  }
},
scrollCallback() {
  // 不超过2000条数据不监听 不分页
  if (!this.cascaderScroll.isScroll) {
    return
  }
  const panel = document.querySelectorAll('.tags .el-scrollbar:nth-child(3) .el-cascader-menu__wrap.el-scrollbar__wrap')
  const length = panel.length
  this.currentScroll = panel[length - 1]
  if (this.currentScroll) {
    this.currentScroll.addEventListener('scroll', this.eventListenerScroll(this.currentScroll))
  }
},
eventListenerScroll(el) {
  return () => {
    // console.log('===========eventListenerScroll===================')
    if (!this.cascaderScroll.page || !this.cascaderScroll.page.totalPage) { // 如果没有分页信息返回
      return
    }
    const scrollTop = el.scrollTop
    const clientHeight = el.clientHeight
    const scrollHeight = el.scrollHeight
    // 滚动条滚动的距离
    const scrollStep = scrollTop - this.scrollValue
    // 更新——滚动前,滚动条距文档顶部的距离
    this.scrollValue = scrollTop
    let direction = 'down'
    if (scrollStep < 0) {
      if (scrollStep <= -160) {
        direction = 'down'
      } else {
        direction = 'up'
      }
    } else {
      direction = 'down'
    }
    console.log(scrollTop + '-------------------------------' + direction)
    // 滚动条到达了底部
    let scroll = false
    if (scrollTop + clientHeight === scrollHeight) {
      if (this.cascaderScroll.page.totalPage > this.cascaderScroll.page.index) {
        console.log('下一页')
        ++this.cascaderScroll.page.index
        scroll = true
      }
    } else if (scrollTop <= 5 && direction === 'up') {
      // console.log('向上滚动')
      if (this.cascaderScroll.page.index > 1) {
        console.log('上一页')
        --this.cascaderScroll.page.index
        scroll = true
      }
    }
    // 需要重新加载数据
    if (scroll) {
   
      console.log('当前页:' + this.cascaderScroll.page.index)
      const start = (this.cascaderScroll.page.index) * 10
      let end = (this.cascaderScroll.page.index + 1) * 10
      if (end > this.cascaderScroll.page.total) {
        end = this.cascaderScroll.page.total
      }
      // console.log('当前页数据===================' + start, end)
      // console.log(this.cascaderScroll.data.slice(start, end))
      this.addOptionData(this.cascaderScroll.data.slice(start, end))

      // 加载完新的数据之后,要让滚动条停留到上次滚动的位置 避免滚动过快 加载数据错误
      setTimeout(() => {
        if (direction === 'up') {
          el.scrollTop = 160
        } else {
          el.scrollTop = 8
        }
      })
    }
  }
},
// 添加数据到options
addOptionData(data) {
  const { pName, tagName } = this.cascaderScroll
  this.options.forEach(tag1 => {
    if (tag1.label === pName) {
      tag1.children.forEach(tags2 => {
        if (tags2.label === tagName) {
          tags2.children = data
        }
      })
    }
  })
},

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值