题干与适用场景
这道前端题考察复杂交互组件的键盘模型与可访问性。重点不是给输入框绑定几个 keydown,而是定义打开、搜索、选择、执行、关闭和恢复焦点的完整状态机,并让屏幕阅读器获得正确的角色、名称和状态。
面试官考察什么
- 能否区分对话框、combobox、listbox 和 menu 的语义。
- 能否设计 Tab、方向键、Enter、Escape、Home、End 的一致行为。
- 能否处理焦点可见、焦点恢复、动态结果、加载和错误状态。
- 能否避免全局快捷键抢占输入、辅助技术或浏览器默认行为。
回答前需要澄清的问题
先确认命令是否分组、是否支持最近记录和异步搜索,移动端是否有入口,快捷键是否可配置,以及执行命令后是否导航、打开弹窗或改变页面状态。还要确认是否允许鼠标与触摸混用,结果数量和加载延迟上限。
30 秒回答框架
我会把面板作为带输入框的模态对话框,输入与结果建立明确的 combobox/listbox 关系。打开时保存触发元素并把焦点移入输入框,方向键移动活动项,Enter 执行,Escape 关闭并恢复焦点。结果变化更新可感知状态,快捷键只在安全上下文触发,并用键盘、读屏和自动化测试覆盖状态迁移。
分步骤深入解答
1. 选择正确的语义边界
外层是可命名的 dialog,输入框根据交互模式使用 combobox 语义,结果容器使用 listbox,选项使用 option。若命令有层级和菜单项,应参考 menu 模式,不要把所有元素都加上 role="menuitem"。ARIA 只描述真实行为,不能用角色掩盖错误的 DOM 结构。
2. 设计焦点和键盘状态机
打开时记录触发按钮,焦点进入输入框;上下方向键在结果间移动,Home/End 跳到首尾,Enter 执行当前项,Escape 关闭。Tab 的行为要与所选模式一致,不能让焦点意外掉到背景。关闭、执行失败或导航后,按场景恢复到触发元素或新的目标位置。
3. 处理动态结果与读屏反馈
搜索结果异步更新时保留输入焦点,更新 aria-activedescendant 或真实焦点,并提供加载、无结果、错误和结果数量提示。不要每个字符都朗读完整列表;用简洁的状态区域汇报变化,确保选中项名称、快捷键和禁用状态可被读到。
4. 控制快捷键和默认行为
打开快捷键应检查当前焦点、组合键和平台差异,避免在输入框、文本编辑器或屏幕阅读器模式下抢占。处理事件前确认是否需要 preventDefault,不要阻止浏览器原生复制、粘贴、查找和辅助技术操作。命令面板也应提供可见按钮入口,不把快捷键作为唯一入口。
5. 让执行、失败和测试可观察
执行命令前显示当前选择,异步命令提供进度或禁用重复提交;失败时保留上下文、说明下一步并允许重试。测试覆盖纯键盘路径、焦点可见、焦点陷阱、Escape 恢复、动态结果、缩放、低速网络和至少一种屏幕阅读器。记录打开、搜索、执行失败和取消等事件,但不要记录敏感输入。
高质量示范回答
我会用一个可命名的 dialog 包住输入框与结果。打开时保存触发按钮,把焦点移到输入框;输入框和 listbox 通过 aria-controls、aria-activedescendant 等关系表达当前选项。上下键、Home/End 移动选择,Enter 执行,Escape 关闭并恢复焦点,Tab 不让焦点掉到背景。异步搜索显示加载、无结果和错误状态,结果数量用简洁的状态提示告知读屏。快捷键检查焦点和平台,不抢占输入或浏览器默认操作,同时提供可见按钮入口。测试覆盖键盘、读屏、缩放、慢网、失败重试和焦点可见,并避免记录搜索中的敏感内容。
常见错误
- 只监听 keydown,没有定义打开、关闭和恢复焦点的状态机。
- 给普通容器乱加 menu、menuitem 或 combobox 角色。
- 动态更新列表后焦点丢失,读屏无法知道当前选项。
- 全局拦截快捷键,破坏输入、复制粘贴和辅助技术行为。
- 没有可见入口,用户必须记住快捷键才能使用。
- 只测鼠标和自动化点击,不测纯键盘、缩放、读屏和慢网络。
追问及应对
应该移动真实焦点还是使用 aria-activedescendant?
两者都可行,取决于组件结构和读屏支持。移动真实焦点更直观,但要维护输入与选项的交互;aria-activedescendant 可保留输入焦点,必须保证引用稳定、选项可感知并覆盖真实设备测试。
搜索结果为空时如何避免焦点陷阱?
保留输入焦点,显示明确的无结果状态,仍允许 Escape 关闭、修改查询或使用其他可见按钮。不要把焦点移到不可操作的占位节点。
命令执行后页面导航了,焦点怎么处理?
由目标页面决定新的焦点位置,例如标题或主要内容;如果仍在原页面,则恢复触发按钮或合理的上下文。执行失败时留在面板并保留输入与错误说明。
如何验证快捷键不会与浏览器冲突?
列出支持的平台和组合键,在输入、编辑器、表单和屏幕阅读器环境中手工验证。只有确实替代默认行为时才阻止事件,并提供设置或按钮作为替代入口。