菜单与表单实战:把交互状态做完整

菜单与表单实战:把交互状态做完整

菜单与表单实战:把交互状态做完整

菜单与表单实战:把交互状态做完整
菜单与表单实战:把交互状态做完整

尚品优品技术编辑 · 原创教程 · 更新于2026年10月23日 · 约7分钟阅读

一个菜单能够点开,一个表单能够显示成功提示,只完成了交互的一部分。用户还会用键盘、重复点击、填错邮箱,或在网络较慢时等待。这篇教程从状态出发搭建菜单和表单,让每个动作都有对应反馈。

一、把折叠菜单写成按钮与内容的关系

菜单按钮使用 button,明确写出它控制哪个区域,并用 aria-expanded 表示当前是否展开。被控制的区域包含正常链接。这样可以将“打开菜单”与“访问页面”两类行为分清楚。

<button id="menu-toggle" aria-controls="site-nav"
  aria-expanded="false">菜单</button>
<nav id="site-nav" hidden>
  <a href="/projects">项目案例</a>
  <a href="/blog">博客</a>
</nav>

按钮激活时同步更新展开状态与 hidden。原生按钮已经支持常见键盘激活方式,不必再把一个 div 模拟成按钮。对于覆盖整个屏幕的复杂菜单,还需要单独考虑焦点移动、关闭操作和背景内容是否可交互。

const toggle = document.querySelector('#menu-toggle');
const nav = document.querySelector('#site-nav');
toggle.addEventListener('click', () => {
  const open = toggle.getAttribute('aria-expanded') === 'true';
  toggle.setAttribute('aria-expanded', String(!open));
  nav.hidden = open;
});

二、先把表单字段与标签写对

每个字段都需要可理解的标签。邮箱使用 email 类型,电话可以使用 tel,必填内容使用 required。不要把所有规则都塞进一段 JavaScript;浏览器已有的输入能力可以作为第一层反馈。占位文字适合提供例子,不能取代字段标签。

<label for="email">联系邮箱</label>
<input id="email" name="email" type="email"
  autocomplete="email" required>
<p id="form-status" role="status"></p>

三、明确提交的五种状态

把状态列成:未提交、填写有误、正在发送、发送成功、发送失败。正在发送时更改按钮文字并避免重复请求;成功时说明用户下一步可以做什么;失败时保留已填写内容,给出重试入口。不要只把按钮变灰,却没有任何解释。

前端校验帮助使用者及时修正输入,服务器仍需对收到的数据进行验证。前端显示成功,也应对应真实的保存或发送结果。如果当前只是本地演示,就应说明数据保存位置,不能把演示提示写成邮件已经送达。

四、把错误提示放到具体字段附近

错误信息应说明怎样改,例如“请输入包含 @ 的有效邮箱地址”,而不是只写“输入错误”。如果使用自定义提示,需要让提示与字段关联;在确实发现无效输入之后,再设置无效状态。不要刚进入页面就把所有空字段标红。

提交失败后不应清空项目需求。较长的表单可在顶部提供错误概览,字段附近保留具体说明。检查读屏与键盘焦点时,确认用户能从概览找到问题字段,也能理解状态变化。

五、用真实操作走完异常路径

测试时先空提交,再输入错误邮箱,再输入完整内容;模拟接口失败后重试,检查按钮是否恢复可用;快速连续点击,检查是否出现重复记录。菜单则测试 Tab、Enter、Space 和关闭后的焦点位置。

最后从首页进入详情,再打开菜单前往博客,连续后退和前进。很多交互故障出现在第二次进入页面,或者跨尺寸切换之后。保留原有动画时,也要让状态控制只有一个来源,避免多个监听器同时开关菜单。

练习任务:给一个联系表单制作成功与失败两种模拟返回,记录每一步的按钮文字、字段内容与状态提示。能清楚解释每个状态,通常也更容易把它实现稳定。

参考资料与继续阅读

本文由尚品优品整理编写,示例用于学习,进一步细节可查阅以下官方资料。

把视觉想法,做成可交付的网站

尚品优品科技有限公司围绕企业业务与品牌表达,提供网站视觉、交互开发与技术实施服务,支持企业直签与营销公司白标合作。