一、问题背景与需求分析
在常见的前端应用场景中,历史聊天记录的加载通常采用上拉加载、下拉刷新的模式。然而,当前面临的特定需求是实现反向的加载方式,即向上滑动(下拉加载)来获取历史聊天记录。这种非传统的加载模式给用户带来了独特的交互体验,但也带来了一系列技术挑战。
二、问题阐述
在传统的上拉加载模式下,新加载出的元素会被添加到页面末尾,此时滚动条位置保持不变,用户体验较为流畅。但在当前反向的加载模式中,当新的聊天记录元素从页面顶部插入时,会导致页面内容向上扩展,从而使滚动条看似向上移动。实际上,滚动条与页面顶端的距离并未改变,只是由于新内容的插入,页面整体被撑开,给用户造成了滚动条向上移动的视觉感受。这种现象不仅影响了用户对页面的直观认知,还可能导致交互过程中的不适应和困惑。
三、解决方案思路
为了解决上述问题,提出了一种基于保持滚动条与页面底部相对距离不变的方法。具体分为以下两个关键步骤:
-
获取与底部的距离:在新元素插入之前,通过计算获取当前滚动条与页面底部的距离。可以使用公式
height = 元素.scrollHeight - 元素.scrollTop
来实现。其中,scrollHeight
表示滚动条的总高度,即整个页面内容的高度;scrollTop
表示滚动条距离页面顶部的高度。通过这个计算,可以准确地得到当前滚动条与页面底部的实际距离值,为后续的调整操作提供依据。 -
调整滚动条位置:在新元素插入之后,为了保持滚动条与底部的相对距离不变,需要重新设置滚动条的位置。具体做法是将
元素.scrollTop
设置为元素.scrollHeight - height
,其中height
是之前获取到的滚动条与底部的距离值。这样,通过调整滚动条向上滚动的距离,使其等于当前页面总高度减去固定的底部距离,从而实现了在新元素插入后,滚动条与底部的相对位置保持不变,有效地解决了因新元素插入导致的滚动条看似向上移动的问题。
通过以上方法,可以在满足反向加载历史聊天记录需求的同时,确保用户在浏览聊天记录时的交互体验更加流畅和自然。
下面是一些实现代码:
// 是否触顶加载中
const refreshing = ref(false) //是否刷新中
const preHeight = ref(0) //加载更多前距离顶部高度
function handleScroll() {
if (msgTotal.value == chatRoomMessageList.value.length) {
console.log('没有更多数据!!!');
return
}
const container = scrollContainer.value;
if (container.scrollTop <= 2) {
if (refreshing.value) {
return
}
preHeight.value = container.scrollHeight - container.scrollTop
refreshing.value = true;
getListRoomMessage() //获取上一页数据
nextTick(() => {
// 计算滚动距离
if (!scrollContainer.value) return;
const currentScrollTop = container.scrollTop;
const targetScrollTop = container.scrollHeight - preHeight.value;
let startTime = null;
const animateScroll = (timestamp) => {
if (!startTime) startTime = timestamp;
const progress = (timestamp - startTime) / 1; // 1ms 内完成滚动动画
if (progress < 1) {
container.scrollTop =
currentScrollTop + (targetScrollTop - currentScrollTop) * progress;
// 开启滚动
requestAnimationFrame(animateScroll);
} else {
container.scrollTop = targetScrollTop;
}
};
requestAnimationFrame(animateScroll);
})
}
}