长列表滚动时可视区域高度计算不准怎么办?
我在用虚拟滚动优化长列表时,发现可视区域高度总是比实际窗口小20px,导致最后几项提前渲染了。之前用window.innerHeight计算容器高度,但加了padding后问题更严重了。
尝试改用容器的getBoundingClientRect(),代码如下:
const container = this.$refs.listContainer;
const viewportHeight = container.getBoundingClientRect().height;
const start = Math.floor((scrollTop) / itemHeight);
const end = Math.ceil((scrollTop + viewportHeight) / itemHeight);
滚动到中间位置时发现end值比预期小,导致底部3项没被渲染。检查发现计算scrollTop时用了container.scrollTop,但容器外层有另一个父元素设置了overflow,实际滚动条在父元素上。该怎么正确获取相对可视区域的滚动位置呢?
document.scrollingElement来拿正确的滚动位置,别管那些乱七八糟的父元素。代码改一下:const container = this.$refs.listContainer;
const parentScroll = document.scrollingElement || document.documentElement;
const scrollTop = parentScroll.scrollTop;
const viewportHeight = container.getBoundingClientRect().height;
const start = Math.floor(scrollTop / itemHeight);
const end = Math.ceil((scrollTop + parentScroll.clientHeight) / itemHeight);
这样就不用纠结容器的嵌套问题了,省事。
正确的做法是用getBoundingClientRect()获取容器的位置信息,结合window.scrollY来计算实际可视区域的滚动位置。修改代码如下: