移动端H5接AI对话的坑:键盘顶起与滚动到底

PC 上跑得好好的 AI 对话框,搬到 H5 上当晚就被测试同学按了一串 bug:输入框被键盘顶飞了、发完消息看不到最新回复、安卓上输入法选词时疯狂触发提交。移动端聊天框这点交互,水比想象深。把我趟过的坑串一遍。

键盘弹起把布局顶乱

iOS Safari 上,软键盘弹起时 window.innerHeight 不变,但可视区域被键盘盖了一截,固定在底部的输入框直接被推到键盘后面看不见。我先用了老办法 position: fixed + 监听 resize,时灵时不灵。

后来换成 visualViewport API,这玩意儿专门描述「真正能看到的那块」:

ini 复制代码
const vv = window.visualViewport!;
function syncInputBar() {
  // 键盘弹起后,可视区底部相对布局视口的偏移
  const offset = window.innerHeight - vv.height - vv.offsetTop;
  inputBar.style.transform = `translateY(-${Math.max(0, offset)}px)`;
}
vv.addEventListener('resize', syncInputBar);
vv.addEventListener('scroll', syncInputBar);

visualViewport 在 iOS 13+ 和现代安卓 webview 都支持了,比起手动监听 focus/blur 加 setTimeout 那套玄学补丁靠谱太多。说实话早几年没这 API 的时候,这块代码丑得我自己都不想看。

发完消息没滚到底

聊天框的天条:新消息进来要自动滚到最新。但有两个坑------

一是流式输出时内容高度一直在涨,得在每个 chunk 后都滚一次;二是如果用户正往上翻历史,你强行拽他到底部会很烦人。所以要判断「用户是不是本来就贴着底」:

ini 复制代码
function isNearBottom(el: HTMLElement, threshold = 80) {
  return el.scrollHeight - el.scrollTop - el.clientHeight < threshold;
}

function onChunk() {
  const stick = isNearBottom(scrollEl);
  appendText();
  if (stick) {
    // 移动端 scrollTo behavior:smooth 在快速流式时会打架,用 instant
    scrollEl.scrollTop = scrollEl.scrollHeight;
  }
}

我一开始用 behavior: 'smooth',结果流式吐字太快,平滑滚动还没到底新内容又来了,画面一直在追着跑、晕得很。换成直接赋值 scrollTop 反而稳。体验上「smooth」在高频场景就是个陷阱。

输入法选词触发提交

安卓上最阴的一个。绑 keydown 监听回车发送,结果用户用拼音输入法选词、按空格/回车确认候选时,也被当成「发送」给提交了,发出一堆半截拼音。

根因是中文输入法的 composition 过程。得用 compositionstart / compositionend 把这段「正在拼字」的窗口圈出来:

ini 复制代码
let composing = false;
input.addEventListener('compositionstart', () => { composing = true; });
input.addEventListener('compositionend', () => { composing = false; });
input.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' && !e.shiftKey && !composing) {
    e.preventDefault();
    submit();
  }
});

!composing 这个守卫一加,乱发拼音的问题当场消失。这个坑不光聊天框,所有带中文输入 + 回车提交的场景都该防。

一个没修干净的

iOS 上输入框 focus 时整个页面偶尔会被系统往上顶一段(rubber-band),visualViewport 也救不全。我加了 document.body.scrollTop = 0 兜底,大部分机型 OK,但某些老款 iPhone 还是会闪一下。这个我至今没根治,属于「能接受的瑕疵」,谁有干净解法求评论区赐教。

模型对话那截我直接接了讯飞 这类 MaaS 的现成 API,不碰后端算力,省下的力气全花在这些移动端交互细节上------前端的活已经够磨人了。

你们 H5 聊天框还踩过啥独门坑?评论区集邮,攒多了我出个续集。

相关推荐
先锋部队1 小时前
给AI对话加「停止生成」按钮:abort SSE实战
人工智能
aqi004 小时前
15天学会AI应用开发(七)有了大模型为什么还要引入RAG
人工智能·python·大模型·ai编程·ai应用
用户5191495848455 小时前
libcurl Headers API 释放后重利用漏洞:跨请求复用头句柄导致堆内存安全风险
人工智能·aigc
踩蚂蚁5 小时前
自定义语音唤醒词:从训练到部署的完整链路实践
人工智能
用户5191495848455 小时前
CVE-2025-1094 PostgreSQL SQL注入与WebSocket劫持远程代码执行利用工具
人工智能·aigc
IT_陈寒6 小时前
SpringBoot自动配置这个坑,我踩进去又爬出来了
前端·人工智能·后端
冬奇Lab18 小时前
Agent 系列(23):Web Agent——让 Agent 真正浏览网页
人工智能·llm·agent