渲染万条数据

万条数据优化

数据展示优化 与实现

叮咚叮咚

  • 小梦:发来一句疑惑`你有没有写过tree 万条数据加载慢的情况
  • 铃木元: 这咋感觉面试常考?
  • 小梦: 你考过?
    铃木小故事开堂啦
    从前的从前,有个人问我,如果你爱我无法自拔,记录了给我的10万条图片列表,你怎么优化展示,做到爱我不卡顿,节省资源?
  • 小梦: 我会懒加载
  • 人: 你这爱我不深哪

身为程序员,怎么能因为代码,而没有对象呢?小梦这就开始研究

列表展示优化

虚拟列表
1. 什么是虚拟列表?

虚拟列表是对于列表形态数据展示的一种按需渲染,是对长列表渲染的一种优化。
虚拟列表不会一次性完整的渲染长列表,而是按需显示的一种方案,以提高无线滚动的性能。

大概就像对着女生需求展示爱,男生才不会有无谓的消耗。

2. 虚拟列表与懒加载有何不同?

懒加载与虚拟列表其实都是延时加载的一种实现,原理相同但场景略有不同。

  • 懒加载的应用场景偏向于网络资源请求,解决网络资源请求过多时,造成的网站响应时间过长的问题。
  • 虚拟列表是对长列表渲染的一种优化,解决大量数据渲染时,造成的渲染性能瓶颈的问题。
    技术不限于框架,但爱你的心相通(原理相同)
3. 虚拟列表的实现原理?

根据日期元素的高度 clientHeight 以及列表项元素的高度 offsetHeight 来显示长列表的某一部分。
请添加图片描述
实现一个虚拟列表需要:

  • 得知容器元素的高度 clientHeight
  • 得知列表项元素的高度 offsetHeight
  • 计算可视区域应该渲染的列表项的个数 count = clientHeight / offsetHeight
  • 计算可视区域数据渲染的起始位置 start
  • 计算可视区域数据渲染的结束位置 end
  • 对完整长列表数据进行截断 sliceList = dataList.slice(start, end)
  • 渲染截断后的列表数据,进而实现无限加载

当滚动过快时,在 viewPort 前后添加缓冲区域 bufferScale

具体实现参考 引用文章

树形展示优化

前情提要

数组转树形

let arr = [
    {id: 1, name: '部门1', pid: 0},
    {id: 2, name: '部门2', pid: 1},
    {id: 3, name: '部门3', pid: 1},
    {id: 4, name: '部门4', pid: 3},
    {id: 5, name: '部门5', pid: 4},
]
// 输出结果: 
[{
        "id": 1,
        "name": "部门1",
        "pid": 0,
        "children": [
            {
                "id": 2,
                 "name": "部门2",
                "pid": 1,
                "children": []
            },
            {
                "id": 3,
                "name": "部门3",
                "pid": 1,
                "children": [
                    // 结果 ,,,
                ]
            }]
    }]
  1. 看到题目,我们一看这不就递归。
/**
 * 递归查找,获取children
 */
const getChildren = (data, result, pid) => {
  for (const item of data) {
    if (item.pid === pid) {
      const newItem = {...item, children: []};
      result.push(newItem);
      getChildren(data, newItem.children, item.id);
    }
  }
}
/**
* 转换方法
*/
const arrayToTree = (data, pid) => {
  const result = [];
  getChildren(data, result, pid)
  return result;
}

开始的时候,blue也是这么搞的。遇到万条数据,他可就原形毕露了。

  • 1次递归时,都去循环1次数组(长度为n),执行次数由数组的长度(n)决定,她的时间复杂度为O(n²)

治标不治本系列

在这里插入图片描述

  • 使用element-ui的el-tree 的 懒加载
  • 懒加载中请求数据中判断是否有下一页,确定添加加载更多按钮否,按钮包含数据要有
    • 为叶子节点
    • 不可修改
    • 当前页数
    • 父节点的 id
    • 加载更多的唯一 id (一棵树可含有多个加载更多按钮,切记区分)
  • 当无下一页的时候,根据 加载更多的唯一id 删除

最优治本

其实不用递归也可以实现。

主要思路也是先把数据转成Map去存储,之后遍历的同时借助对象的引用,直接从Map找对应的数据做存储。在遍历的时候即做Map存储,有找对应关系。性能会更好。

function arrayToTree(items) {
  const result = [];   // 存放结果集
  const itemMap = {};  // 
  for (const item of items) {
    const id = item.id;
    const pid = item.pid;

    if (!itemMap[id]) {
      itemMap[id] = {
        children: [],
      }
    }

    itemMap[id] = {
      ...item,
      children: itemMap[id]['children']
    }

    const treeItem =  itemMap[id];

    if (pid === 0) {
      result.push(treeItem);
    } else {
      if (!itemMap[pid]) {
        itemMap[pid] = {
          children: [],
        }
      }
      itemMap[pid].children.push(treeItem)
    }
  }
  return result;
}

一次循环搞定,时间复杂度为O(n)

引用文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值