题干与适用场景
产品希望在用户对用户名、文档链接或术语“感兴趣”时显示轻量预览,但不能因为 hover 丢失、键盘操作或触摸设备而让内容不可用。请使用 HTML interest invoker 与 Popover API 设计方案,并说明延迟、焦点、关闭、浏览器不支持和数据加载失败时的处理。
MDN 将 interestfor 描述为把按钮或链接关联到目标元素的声明式机制;当目标是 popover 时,浏览器可在显示 interest 时自动显示它。Open UI explainer 记录了 hovercard 的设计动机。本文基于公开资料整理,不声称是公司真题。
面试官考察点
面试官关注你是否把“悬停”提升为统一的 interest 状态,覆盖 pointer、focus、触摸和辅助技术。强回答会提到 interest/loseinterest、interest-delay-*、popover 的 top layer、焦点管理、无 JavaScript 核心路径与渐进增强;普通回答只绑定 mouseenter/mouseleave。
回答前需要澄清的问题
- 预览是补充信息,还是完成任务所必需?
- 目标内容是否同源、可缓存,是否允许延迟加载?
- 触摸设备如何触发和关闭,是否需要点击进入详情页?
- 浏览器尚不支持 interest invoker 时,核心链接如何保持可用?
30 秒回答框架
“我会让普通链接仍然指向详情页,再用 interestfor 把链接关联到一个 popover 预览。通过 interest delay 减少误触发,浏览器支持时由声明式行为处理 pointer 与 focus;不支持时不影响链接,必要时用最小 JS polyfill。预览内容可异步加载但不能阻塞导航,关闭时尊重焦点和 Escape 语义,并在减少动效时去掉动画。”
分步骤深入解答
结构上,链接或按钮是 interest invoker,目标元素拥有稳定 id 和 popover。invoker 的 interestfor 值引用目标 id。目标是 popover 时,平台负责把它放进 top layer 并应用 popover 生命周期;目标也可以只是普通元素,供应用监听 interest 事件后决定是否显示。
延迟策略避免用户快速扫过链接时产生大量请求。使用 interest-delay-start 和 interest-delay-end 或等价的应用节流,先显示骨架,再按缓存键请求预览。离开 invoker、进入目标 popover 或快速移动到另一个链接时,要取消未完成请求并只保留最后一次意图。
键盘和触摸不能依赖 hover。焦点落到链接时应能显示同一预览,Escape 可关闭,Tab 顺序仍通向详情。触摸设备可在第一次点击展示预览、第二次点击导航,或直接导航并提供独立的预览按钮;产品应选择一种可解释的规则,避免手势冲突。
可访问性要求目标有可读名称、正确的关系和状态反馈。预览是补充信息时不要强制焦点跳入 popover;若内容包含可交互控件,则需要明确的焦点进入和返回路径。屏幕阅读器用户应能直接访问详情页,不因预览加载失败而失去信息。
能力检测与回退保持核心路径。没有 interestfor 或 Popover API 时,链接照常导航,预览可退化为点击展开或完全省略。若使用 polyfill,只补充显示行为,不复制 top-layer、焦点和安全边界的全部实现;记录支持率、预览打开率、加载失败率和导航转化。
高质量示范回答
我会把链接作为核心导航,把 interest invoker 作为可选预览层。interestfor 关联稳定 id,目标使用 popover;平台处理 pointer/focus 的 interest,延迟和缓存控制请求。键盘可聚焦、Escape 可关闭,触摸采用明确的点击规则。浏览器不支持时保留普通链接,预览失败只影响补充层,不影响详情访问。
常见错误
- 错误表现 → 只监听 mouseenter;失败原因 → 键盘、触摸和辅助技术无法触发;修正方法 → 以 interest 与 focus 为核心,并保留导航。
- 错误表现 → 预览一出现就把焦点移入;失败原因 → 用户阅读链接时被打断;修正方法 → 仅在预览含交互控件且有明确规则时移动焦点。
- 错误表现 → 每次悬停都请求网络;失败原因 → 快速扫过造成请求风暴;修正方法 → 使用延迟、取消、缓存和最后意图胜出。
- 错误表现 → 不支持时阻止链接;失败原因 → 核心内容被实验 API 绑架;修正方法 → 普通链接作为无条件回退。
追问及应对
为什么预览目标不一定需要 popover?
interestfor 可以把 invoker 与普通目标关联,应用监听 interest 事件后自行控制显示;当目标是 popover 时,平台提供 top layer 和关闭语义。选择取决于是否需要原生生命周期与轻量声明式行为。
如何避免预览遮挡另一个链接?
为目标设置稳定定位和碰撞策略,离开时使用结束延迟,进入 popover 视为仍有兴趣。快速切换时取消旧请求、关闭旧目标并只提交最新 invoker 的结果。
预览加载失败时应怎样反馈?
在预览层显示可重试的简短状态,并提供直接详情链接;不要把错误扩散到页面主内容。记录失败原因和延迟,超过预算时跳过预览动画或直接导航。