Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tree] 使用虚拟滚动的树形组件,滚动条滑块的高度不正常 #2288

Open
sagittarius-rev opened this issue Mar 31, 2023 · 4 comments

Comments

@sagittarius-rev
Copy link

sagittarius-rev commented Mar 31, 2023

tdesign-vue 版本

tdesign-vue 1.2.3

重现链接

https://codesandbox.io/s/tdesign-vue-demo-forked-zp2xje?file=/src/demo.vue

重现步骤

使用树形组件,启用虚拟滚动功能, type 设置为 "virtual" 。在组件内使用数量较多的节点。

滚动界面。

期望结果

右侧滚动条的滑块应当正常显示。按照当前可见区域的高度,以及整棵树渲染出来的高度,滑块高度应当遵循两者的比例。

也就是,树高度越大,滚动条滑块的高度应当越小,两者成反比关系(假设可见区域的高度不变)。

在纵向滚动过程中,滑块的高度应当不发生变化,只是位置在移动。

实际结果

初始情况下,滑块高度较大。而随着向下滚动,滑块会逐渐缩小。

如果数据量较多,拖动滚动条时,无法一次拖动就滚动到底部。需要分很多次进行滚动操作,才能到底。

框架版本

Vue(2.6.14)

浏览器版本

Chrome(109.0.5414.120)

系统版本

Windows 10

Node版本

16.16.0

补充说明

问题原因分析

虚拟滚动的树形组件,在组件上设置了 overflow: scroll 样式。右侧的滚动条是由浏览器自行渲染出来的。

而浏览器计算滚动条滑块高度时,会根据当前组件的实际占据范围为依据。使用虚拟滚动功能的时候,树形组件内只渲染了部分节点,并设置 transform: translate() 的样式进行位移。这样,浏览器计算树形组件占据的范围时,会以位移之后的节点组件底部为依据。

在初始情况下,渲染出来的节点会比可见范围能容纳的节点多一些,根据 bufferSize 属性的设置决定。此时,浏览器认为树形组件的实际高度范围只比可见区域高度多一些,因此计算出来的滚动条滑块高度就较大。

而随着不断向下滚动,渲染出来的可见节点在发生变化,位移值也在增加。因此,浏览器认为树形组件占据的高度范围在增加,滚动条滑块的高度就随之减少了(如前面所述的反比关系)。

解决方案

在树形组件内部附加一个用于占位的元素,可以设为不可见(不使用 display: none ,而是使用 opacity: 0visibility: hidden )。元素使用绝对定位,其纵向位置是动态计算的,相当于整棵树渲染出来时最后一个节点的底部位置。

有了这个占位元素之后,浏览器就能正确判断树形组件应当占据的有效高度范围,从而正常渲染滚动条的滑块高度。而这个高度在滚动过程中不会发生变化。

重现链接中就实现了对应的功能。点击页面上的“插入定位锚点”按钮,就会插入前述的占位元素,保证滚动条外观正常。而在节点展开/折叠的时候,会重新计算该元素的位置(理论上在数据重置、增加项目、减少项目时,也应当进行重算,但示例代码未进行这些处理)。

理论上只要每行的高度是固定的,那么只要知道有多少元素应当被显示,就能计算出占位元素的纵向位置。

但目前 TDesign 的树形组件没有暴露出相关的处理方法或属性。因此重现链接中的代码是通过一些内部属性来对此进行计算的:

treeRef._vnode.componentInstance.state.nodes.value.filter(node => node.visible).length

代码比较丑陋。

希望官方能内置相关的特性支持。

@github-actions
Copy link
Contributor

👋 @sagittarius-rev,感谢给 TDesign 提出了 issue。
请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。

@github-actions
Copy link
Contributor

github-actions bot commented Mar 31, 2023

♥️ 有劳 @TabSpace 尽快确认问题。
确认有效后将下一步计划和可能需要的时间回复给 @sagittarius-rev

@TabSpace
Copy link
Collaborator

TabSpace commented Apr 21, 2023

目前虚拟滚动复用了 table 的虚拟滚动代码,先解决了有没有这个能力的问题。
该 hooks 适配了每行高度不固定的情况,tree 也应当适配这个能力,如果有这方面问题则属于待修改的 bug。
默认行高确定的情况,应当是可以得到确定的滑块高度的。
需要小心的是,filter 能力, expand 能力,可能也与此关联,会触发滑块高度变更,也需要验证解决方案。
当前虚拟滚动能力有不完善的地方,后续会做进一步改进。

@chaishi
Copy link
Collaborator

chaishi commented Nov 30, 2023

Table 的虚拟滚动,支持预估滑块的默认高度, 是按比例来的,可以参考下 @TabSpace

大概原理是:rowHeight * data.length,如果 rowHeight 不存在,则取第一行的高度。

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants