聊天机器人 : Auto Scroll 聊天窗口自动滚动
聊天机器人 : Auto Scroll 聊天窗口自动滚动
一、前言
在之前的开发中,我们已经完成了聊天消息的渲染、Markdown 渲染以及代码高亮。
但是,当聊天记录越来越长时,会出现一个新的问题:
当 AI 生成新的回复时,聊天窗口不会自动移动到最新消息的位置。
用户可能需要手动滚动页面才能看到 AI 正在生成的内容,这会影响聊天体验。
因此,今天我们来学习 Auto Scroll,也就是聊天窗口的自动滚动功能。
二、理解三个核心属性
在实现自动滚动之前,需要先理解 JavaScript 中与滚动相关的三个属性。
1. scrollTop
scrollTop 表示元素内容向上滚动的距离。
例如,聊天窗口向下滚动了 300px:
console.log(chatBox.scrollTop);
此时,返回值可能是 300。
我们也可以通过修改它来控制滚动位置:
chatBox.scrollTop = 300;
2. scrollHeight
scrollHeight 表示元素内容的整体高度,包括当前可视区域之外的内容。
例如,聊天窗口的可视区域只有 500px,但聊天记录已经有 2000px 高,那么 scrollHeight 就可能接近 2000。
console.log(chatBox.scrollHeight);
3. clientHeight
clientHeight 表示元素可视区域的高度。
console.log(chatBox.clientHeight);
假设聊天窗口的可视区域高度为 500px,那么 clientHeight 就是 500。
4. 三个属性之间的关系
可以简单理解为:
| 属性 | 含义 |
|---|---|
scrollTop | 已经向下滚动了多少 |
scrollHeight | 内容总共有多高 |
clientHeight | 当前能看到的区域有多高 |
当用户滚动到最底部时,通常满足:
scrollTop + clientHeight >= scrollHeight
因此,我们可以利用这些属性判断用户是否已经接近聊天窗口的底部。
三、实现基础自动滚动
理解了这三个属性后,实现自动滚动就很简单了。
假设我们的聊天窗口对应一个 DOM 元素:
const chatBox = document.getElementById("chat-box");
当新增一条消息后,只需要执行:
chatBox.scrollTop = chatBox.scrollHeight;
这行代码的含义是:
将当前滚动位置设置为内容的整体高度,使聊天窗口滚动到最新内容的位置。
也可以使用 scrollTo():
chatBox.scrollTo({
top: chatBox.scrollHeight,
behavior: "smooth"
});
其中:
top:目标滚动位置。behavior: "smooth":使用平滑滚动效果。
需要注意,自动滚动应该发生在新消息加入 DOM 之后,否则计算到的 scrollHeight 可能还是更新之前的高度。
四、Streaming 场景下的自动滚动
在普通聊天中,一条消息通常一次性显示出来。
但在 KK Chat 中,我们使用了 Streaming,让 AI 的回复逐步输出。
例如:
你好
你好!很高兴
你好!很高兴认识你。
随着新内容不断追加,消息区域的高度也可能持续变化。
如果只在创建消息时滚动一次,那么当 AI 继续生成长文本时,用户仍然可能看不到最新内容。
因此,我们需要在 Streaming 更新消息内容时,也执行滚动处理。
1. 基础实现
假设我们已经创建了 AI 回复对应的消息元素:
function updateAssistantMessage(messageElement, content) {
messageElement.textContent = content;
chatBox.scrollTop = chatBox.scrollHeight;
}
每次收到新的内容后,更新消息并滚动到底部。
这里的 messageElement 是 AI 回复对应的 DOM 元素,content 是当前要显示的文本。
这只是一个简化示例,实际项目中还需要根据自己的 Streaming 逻辑决定如何追加文本,以及何时重新渲染 Markdown。
2. 为什么不能始终强制滚动?
假设 AI 正在生成一篇很长的回答。
用户为了查看上面的内容,手动向上滚动了一段距离。
此时,如果每收到一个新的 Streaming 数据片段,就强制执行:
chatBox.scrollTop = chatBox.scrollHeight;
聊天窗口就会立刻跳回底部。
用户无法继续阅读之前的内容。
因此,更合理的方案是:
只有当用户原本就在底部附近时,才自动跟随新内容滚动。
3. 优化:判断用户是否接近底部
首先,编写一个判断函数:
function isNearBottom(element) {
return (
element.scrollHeight -
element.scrollTop -
element.clientHeight
) < 80;
}
这里的 80 表示容许的距离阈值,单位是 CSS 像素。
如果距离底部不足 80px,就认为用户仍然希望跟随最新消息。
接下来,在更新消息之前记录用户的位置:
function updateAssistantMessage(messageElement, content) {
const shouldAutoScroll = isNearBottom(chatBox);
messageElement.textContent = content;
if (shouldAutoScroll) {
chatBox.scrollTop = chatBox.scrollHeight;
}
}
这里有一个关键细节:
必须在更新消息内容之前判断用户是否接近底部。
因为更新内容后,scrollHeight 可能已经发生变化。如果在更新之后才判断,可能无法准确反映用户更新前的位置。
通过这种方式,我们就能兼顾两种情况:
- 用户正在底部查看最新回复:自动跟随。
- 用户主动向上阅读历史内容:不强制跳回底部。
五、实践中需要注意的问题
1. 为什么设置 scrollTop 后没有滚动?
首先检查三个方面:
chatBox是否正确获取了 DOM 元素。- 聊天窗口是否真的存在可滚动的内容。
- CSS 是否正确设置了聊天区域的高度和
overflow-y。
例如:
#chat-box {
height: 500px;
overflow-y: auto;
}
如果元素没有形成独立的滚动区域,实际滚动的可能是整个页面,而不是聊天窗口本身。
2. 为什么 Streaming 时滚动不够及时?
因为 Streaming 会持续更新消息内容,内容高度也可能随之改变。
因此,自动滚动逻辑需要与消息更新过程配合,而不是只在用户发送消息时执行一次。
对于高频更新的场景,还可以使用 requestAnimationFrame() 合并滚动操作,避免在短时间内重复执行过多次滚动。但在基础版本中,可以先使用简单实现。
3. 为什么不能无条件滚动到底部?
因为自动滚动不仅要考虑程序的行为,也要考虑用户当前的操作。
如果用户正在阅读历史消息,程序不断强制滚动到底部,就会打断阅读。
因此,自动滚动的核心并不是每次都滚到底,而是判断用户是否仍然希望跟随最新内容。
六、总结
今天我们学习了 Auto Scroll 的基本原理与实现方式。
主要知识点包括:
scrollTop:当前滚动位置。scrollHeight:内容整体高度。clientHeight:可视区域高度。- 使用
scrollTop = scrollHeight实现基础自动滚动。 - 在 Streaming 更新消息时同步处理滚动。
- 通过判断用户是否接近底部,避免打断用户阅读历史消息。
Auto Scroll 看起来只是一个小功能,但它体现了前端开发中一个重要的思路:
功能实现只是第一步,还需要考虑用户在真实使用场景中的体验。
对于 KK Chat 来说,消息渲染、Streaming、Markdown、代码高亮和自动滚动共同组成了一个完整的聊天交互流程。
下一步,可以继续优化聊天界面的交互体验,例如处理代码块渲染后的滚动、长消息布局,以及用户手动滚动时的行为。
KJ
项目:KK Chat
系列:《从零开发 AI Chatbot》
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)