Skip to content

AI 场景

AI 对话是虚拟滚动最难的一类场景:内容持续变化、高度完全不可预知、 用户和程序同时在滚动。先看效果——

微应用尚未挂载。

点一个快捷提示或自己输入一句发送,试着在生成过程中向上滚、再滚回底部。 生成过程里会依次插入思考、工具调用、代码块——每一次插入都是一次高度跳变。 每个动作的预期行为见 流式输出与贴底跟随

这一节不是新的 API,而是把已有能力组合起来解决这类场景的方法。

为什么普通虚拟列表在这里会失稳

场景特征常见实现为什么出问题
流式输出:一条消息的高度每几十毫秒变一次若按「测出新尺寸 → 按差值补偿滚动偏移」处理,误差会逐次累积,而补偿本身又触发新的滚动事件,很容易抖动甚至回弹
边生成边滚动,用户随时可能上滑去读历史多数实现分不清 scrollTop 是用户改的还是程序改的,只能靠「上次程序化写入的值」去猜,与异步滚动事件构成竞态
消息里有代码块、表格、公式,渲染成本高项反复进出视口就反复重渲染,长回答滚动时掉帧
几万条历史,需要往上翻头部插入数据后视口内容被推走,需要手动补偿位移

这套实现的应对

两个设计选择决定了上面四种情形不会失稳。

一、把「视觉上该维持什么」表达成一个可求解的目标,而不是一串增量补偿。 尺寸每次变化都重新求解这个目标,而不是累加位移。因为求解的是不变量, 重复执行是幂等的——不需要收敛判据,也不需要重试上限。 流式输出下的稳定跟随、头部插入后的位移补偿、折叠长消息后的位置维持, 在这个模型里是同一件事的不同分支,而不是三套互相打架的补偿逻辑。

二、滚动来源是确定的,不是猜的。 偏移量由 JS 掌管(容器 overflow: hidden),用户输入与程序化定位走两个不同的入口。 于是「这次滚动是谁发起的」在代码里是已知量,"用户一上滑就解除跟随"这类判断 不依赖任何时间窗口,也就不存在与异步滚动事件的竞态。

具体做法

相关基础

这两页假设你已经了解 分页与无限加载 里的 loadMore 模型。 若想了解跟随背后的滚动机制,可以读 滚动是怎么工作的