找回密码
 立即注册

QQ登录

只需一步,快速开始

Richard.Huang SpreadJS 开发认证

超级版主

43

主题

3222

帖子

4999

积分

超级版主

Rank: 8Rank: 8

积分
4999

SpreadJS 认证SpreadJS 高级认证

Richard.Huang SpreadJS 开发认证
超级版主   /  发表于:2024-4-26 14:01  /   查看:1097  /  回复:0
背景

常常有用户会有树形结构的报表渲染的需要,而实现方式也很简单,就是数据绑定+分组列,从而实现一个树形结构的数据展示。但是当数据量上去后,前端的性能瓶颈就会很明显,卡顿延迟会让很多用户抓狂,那么我们是否有方案能够对这种场景做优化呢?本文先来探讨其中一种能够想到的方案:动态渲染

实现方式

我们可以看到,实际我们报表能够查看的只有一部分,特别是没有展开的数据,大家能看到的就更少了,那么我们可不可以就这种常见的查看方式来针对性的动态渲染呢?即,初始化时,我们先渲染一级节点,等用户点击展开时,我们再动态对应的一级节点下的二级节点进行渲染,以此类推。
image.png461222228.png
这其中有几个关键点需要注意:
1. 我们除了需要渲染的数据以外,我们还需要知道该数据是几级节点
2. 我们需要监听用户的展开的按钮操作,然后去动态在下面位置插入数据

代码示例
1. 一级节点初始化渲染
  1. sheet.setDataSource(new GC.Spread.Sheets.Bindings.CellBindingSource(data))// 一级节点数据覆盖
复制代码
2. 展开按钮单元格类型自定义
  1. // 自定义一个有下拉icon的单元格
  2. function CustomCellType() {
  3.     this.RADIUS = 10;
  4.     spreadNS.CellTypes.Text.apply(this);
  5. }

  6. CustomCellType.prototype = new spreadNS.CellTypes.Text();
  7. CustomCellType.prototype.paint = function (ctx, value, x, y, w, h, style, context) {
  8.     spreadNS.CellTypes.Text.prototype.paint.apply(this, arguments);
  9.     if (!ctx) {
  10.         return;
  11.     }

  12.     // 画个倒三角
  13.     ctx.save();
  14.     ctx.rect(x, y, w, h);
  15.     ctx.clip();
  16.     ctx.beginPath();

  17.     ctx.fillStyle = "red";
  18.     var triangleSize = Math.min(w, h) / 4;
  19.     var centerX = x + w * 0.9;
  20.     var centerY = y + h / 2;
  21.     ctx.moveTo(centerX - triangleSize, centerY - triangleSize / 2);
  22.     ctx.lineTo(centerX + triangleSize, centerY - triangleSize / 2);
  23.     ctx.lineTo(centerX, centerY + triangleSize);
  24.     ctx.closePath();
  25.     ctx.fill();
  26.     ctx.restore();
  27. };
复制代码
3. 展开动作数据插入逻辑
  1. // 点击展开icon,鼠标松开时执行以下逻辑
  2. CustomCellType.prototype.processMouseUp = function (hitInfo) {
  3.     if (hitInfo.isReservedLocation) {// 判断是icon区域
  4.         var sheet = hitInfo.sheet;// 当前工作表
  5.         var tag = sheet.getTag(hitInfo.row, hitInfo.col, hitInfo.sheetArea);// 单元格隐藏信息
  6.         if (tag !== undefined && (tag.isCollapsed === undefined || tag.isCollapsed === false)) {// 避免重复展开重复添加数据和请求数据
  7.             var data = secondData[tag.请求地址];// 这里模拟从后台获取数据
  8.             if (data === undefined) {
  9.                 alert("请求数据失败")
  10.                 return
  11.             }
  12.             sheet.suspendPaint()
  13.             sheet.addRows(hitInfo.row + 1, data.length)// 添加空行
  14.             data.forEach((value, index) => {
  15.                 sheet.setValue(hitInfo.row + 1 + index, hitInfo.col, value.value)// 填值
  16.                 if (value.tag !== undefined) {
  17.                     sheet.setTag(hitInfo.row + 1 + index, 0, value.tag); // 隐藏属性
  18.                     sheet.getCell(hitInfo.row + 1 + index, 0).textIndent(value.tag.level);// 文本缩进,这样看上去像棵树
  19.                     if (value.tag.请求地址) {
  20.                         sheet.setCellType(hitInfo.row + 1 + index, 0, new CustomCellType())
  21.                     }
  22.                 }
  23.             })
  24.             tag.isCollapsed = true// 当前单元格下已经展开了,不要再展开了
  25.         }
  26.         sheet.autoFitColumn(hitInfo.col)
  27.         sheet.setColumnWidth(hitInfo.col, sheet.getColumnWidth(hitInfo.col) + 30)
  28.         sheet.resumePaint()
  29.     }
  30. };
复制代码
完整代码
动态加载数据.html (15.2 KB, 下载次数: 252)

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部