当element中的tree组件数据量超过万条处理方式

就是很普通的树形结构,所存在的问题就是,返回的数据中,子集可能有几条几万条不等,存在的问题也显而易见了

数据量过大,样式越复杂,浏览器舒渲染的过程就会越慢。

这大概就是项目需求

html
	  // 这里我使用的是render-content方式生成tree组件样式
      <div class="cont" ref="list" @scroll="handleScroll($event)">
        <el-tree
          class="filter-tree"
          :style="{ transform: getTransform, height: listHeight + 'px' }"
          ref="tree"
          accordion
          :data="newList"
          :props="defaultProps"
          :default-expand-all="false"
          :filter-node-method="filterNode"
          :render-content="renderContent"
          :expand-on-click-node="false"
          :render-after-expand="false"
          :check-on-click-node="true"
          @node-click="handleNodeClick"
          @node-expand="handleOpen"
          @node-collapse="handleClose"
        ></el-tree>
      </div>
js,首先将原数据存在vuex中

1.绑定scroll,让可视区域编程虚拟列表,实时替换子集

思路

  • 计算出可视区域和滑动后的索引位置
  • 与原数组对比,实时更新新数组
  • 计算偏移量,让用户可以一直滚动
<script>
export default {
  name: 'TreeFunction',
  props: {
    treeList: {
      type: Array,
      required: true,
      default: () => []
    },
    tabTopTypeApprove: {
      type: String,
      required: false,
      default: 'plan'
    }
  },
  data () {
    return {
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      screenHeight: 0, // 可视区域高度
      startOffset: 0, // 偏移量
      start: 0, // 起始索引
      end: null, // 结束索引
      itemSize: 24, // 每项高度
      treeAllList: 0,
      newList: [],
      terrClickKey: ''
    }
  },
  watch: {
  	// 因为是组件,这边监听传入的值第一次初始化
    dataList: {
      handler: function (val, oldVal) {
        // eslint-disable-next-line prefer-const
        let treeStandardList = JSON.parse(
          JSON.stringify(this.$store.state.user.treeStandardList)
        )
        treeStandardList.forEach((_) => {
          if (_.children && _.children.length > 20) {
            _.children = _.children.slice(0, 12)
          }
        })
        this.newList = treeStandardList
      },
      deep: true
    }
  },
  computed: {
    dataList () {
      return this.treeList
    },
    visibleCount () {
      const clientHeight = this.$el.clientHeight - 36 // 当前容器可视区域
      return Math.ceil(clientHeight / this.itemSize)
    }, // 当前列表可显示多少条
    // 偏移量对应的style
    getTransform () {
      return `translate3d(0,${this.startOffset}px,0)`
    },
    listHeight () {
      // 我的默认高度是277
      return !this.treeAllList ? 277 : this.treeAllList
    }
  },
  mounted () {},
  created () {},
  methods: {
    renderContent (h, { node, data, store }) {
    // TO DO
    // 这个太长了,就...
	},
    handleOpen (data, node) {
      this.terrClickKey = data.label
    },
    handleScroll (e) {
      const scrollTop = this.$refs.list.scrollTop // 当前滚动条
      this.start = Math.floor(scrollTop / this.itemSize) // 索引开始位置
      this.end = this.start + this.visibleCount
      // eslint-disable-next-line prefer-const
      let treeStandardList = JSON.parse(
        JSON.stringify(this.$store.state.user.treeStandardList)
      )
      // eslint-disable-next-line no-unused-vars
      let list = []
      // eslint-disable-next-line no-unused-vars
      let allHeight = 0
      // 找到原始数组,找出对应下标的数组
      treeStandardList.forEach((_) => {
        if (this.terrClickKey === _.label) {
          allHeight = _.children.length * this.itemSize
          if (!allHeight) {
            return false
          } else {
            list = _.children.slice(
              this.start,
              Math.min(this.end, _.children.length)
            )
          }
        }
      })
	  // 找到现在使用的数组进行进行替换(这边没有返回唯一key或者id之类的东西,我只能用名称对比了)
      this.newList.forEach((_) => {
        if (this.terrClickKey === _.label) {
          _.children = list
        }
      })
     
      this.treeAllList = allHeight // 设置高度
      this.startOffset =
        scrollTop > allHeight
          ? allHeight
          : scrollTop
            ? scrollTop - ((scrollTop % this.itemSize) + 24)
            : 0 // 此时的偏移量 加了24px是因为父级高度会在最上方
    }
  }
}
</script>
后面再说两种思路吧

2.同样使用虚拟列表的方式,只是采用的向数组添加和移除无用的数据

3.自己模拟个翻页功能

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值