Closed liupan1890 closed 2 years ago
<div class="arco-tree arco-tree-checkable arco-tree-size-medium" style="height: 360px">
<div style="overflow-y: auto; overflow-anchor: none; max-height: 360px">
<div style="height: 1.17183e6px; position: relative; overflow: hidden; z-index: 0">
<div style="display: flex; flex-direction: column; transform: translateY(439px); position: absolute; left: 0px; right: 0px; top: 0px">
<div class="arco-tree-node arco-tree-node-is-leaf arco-tree-node-expanded arco-tree-node-disabled-selectable">...</div>
<div class="arco-tree-node arco-tree-node-is-leaf arco-tree-node-expanded arco-tree-node-disabled-selectable">...</div>
<div class="arco-tree-node arco-tree-node-is-leaf arco-tree-node-expanded arco-tree-node-disabled-selectable">...</div>
<div class="arco-tree-node arco-tree-node-is-leaf arco-tree-node-expanded arco-tree-node-disabled-selectable">...</div>
...
</div>
</div>
</div>
</div>
这是dom树 如截图中,滚动条在顶部时,
<div class="arco-tree arco-tree-checkable arco-tree-size-medium" style="height: 360px">
<div style="overflow-y: auto; overflow-anchor: none; max-height: 360px">
<div style="height: 1.17183e6px; position: relative; overflow: hidden; z-index: 0">
外部的3层,都没问题,显示都是正确的。只有
<div style="display: flex; flex-direction: column; transform: translateY(439px); position: absolute; left: 0px; right: 0px; top: 0px">
这一层,有问题,位置/高度不对(或者说里面的<div class="arco-tree-node 数量不对,显示的太少,不足以占满)
感觉应该是arco的BUG
@liupan1890 好的,我们会排查一下
在v2.8.0
web-vue\lib_components\virtual-list\virtual-list.vue_vue&type=script&lang.js
100行: const visibleCount = vue.computed(() => Math.ceil(viewportHeight.value / itemHeight.value));
web-vue\lib_components\virtual-list\hooks\use-item-height.js
vue.watch(itemLength, () => {
if (itemLength.value && !estimatedItemHeight.value) {
estimatedItemHeight.value = Object.entries(itemHeightCacheMap.value).reduce((sum, [, height]) => sum + height, 0) / itemLength.value;
}
});
由以上代码可知: 1.初始化后会计算出itemHeightCacheMap里全部item的平均高度(itemHeight) 2.根据这个平均高度,确定显示多少行记录
这个逻辑明显是错误的
在我的实际使用时,1000行记录,高度不固定(文件名很长时会自动换行显示成2行文字)(不长时显示为一行文字) 因为高度不固定,此时计算出的平均高度,也不准确。进而导致visibleCount太少,最后导致这个Tree滚动错位问题
--
平均高度?这个思路不准确, 1.因为行高滚动后可能会变,变动小或不变动时,就能正确显示,当变动大时就不能正确显示 2.因为数据比较多时,如果其中有一半行高度特别高,这种情况下,滚动时,因为高度被平均,必然会错位
举例: 1-100行 高度都是32px 101-200 高度是56px 假设viewportHeight=440px,完整滚动一遍后,计算出平均高度(itemHeight)=44px,visibleCount=10 此时,滚动到1-100行位置时,必然因为10*32px=320px导致无法占满viewportHeight,上面或这下面会有大段空白
--
简单的修正办法,是强制增加visibleCount (+20)
100行: const visibleCount = vue.computed(() => Math.ceil(viewportHeight.value / itemHeight.value)+20);
正确的修正办法,是重新规划visibleCount的计算思路
--
我就是在等着官方更新期间,简单的翻翻代码,可能理解的不够全面,但在我一个简单的文件树页面,确实发现了这个问题,这个逻辑
@Flsion
因为List控件虚拟化时,也是使用的web-vue\lib_components\virtual-list 由此可见,此BUG也会导致List组件的显示错位。
List / Select / Table / Tree
这4个组件都是基于virtual-list的啊,arco-design-vue已经发布半年了,不可能才发现有这个BUG吧?
平均高度?
你好,计算 visibleCount 确实比较粗暴一些,这个计算的出发点是想要尽量减少计算量,这样的计算方式对于行高没有太大差异的情况运行还是蛮好的,但是像同学提出的这种行高差异较大的情况确实有问题,我们会再优化一波计算方式。
@kirazxyun 为了性能,相对合理的,代码变动最小的,应该是取最小行高,而不是取平均行高
如上例, 最小行高是32px,依此计算出visibleCount =440/32=13.7行=14行 平均行高是44px,依此计算出visibleCount =440/44=10行=显示错误,有空白
采用平均行高时,440px的框,空白120px,空白30%,这个太明显了 采用最小行高,仅仅需要修改一行
estimatedItemHeight.value = Object.entries(itemHeightCacheMap.value).reduce((sum, [, height]) => sum + height, 0) / itemLength.value;
estimatedItemHeight.value = Object.entries(itemHeightCacheMap.value).reduce((sum, [, height]) => Math.min(sum ,height), 0);
逻辑没变。但可以修正BUG
v2.9.0 List 底部空白
Basic Info
What is expected?
正确显示
Steps to reproduce
Tree绑定大量数据后,显示时错位,不知道是否和现实的数据有关,显示的是文件名,长度有长有短