最稳妥方案是监听 table 的 mouseover 事件,用 event.target.closest('td') 获取目标单元格;title 属性无法满足焦点提示的可访问性与样式需求,应改用动态添加 class、设置 tabindex="-1" 并调用 focus() 实现;需配合 mouseleave 清除焦点,并通过键盘方向键维护 currentCell 确保鼠标与键盘导航高亮一致。

鼠标移入时如何准确获取目标 <td> 元素
直接监听 table 的 mouseover 事件最稳妥,避免为每个 <td> 单独绑定事件导致性能浪费或动态添加单元格时失效。关键是要用 event.target 并向上查找最近的 <td>,因为鼠标可能落在子元素(如文字、<span>)上,而非 <td> 本身。
常见错误是直接判断 event.target.tagName === 'TD',结果在单元格内有嵌套标签时漏匹配。正确做法:
table.addEventListener('mouseover', (e) => {
const td = e.target.closest('td');
if (!td) return;
// 此时 td 就是真正被鼠标进入的单元格
});
为什么不能用 title 属性实现焦点提示
title 是浏览器原生提示,无法控制样式、位置、延迟或触发时机,且在移动端基本不可靠;更重要的是,它和“焦点”语义无关——title 不响应键盘导航,也不与 tabindex 或 focus 状态联动,纯属 tooltip 替代方案,违背“焦点提示”的交互意图。
真正需要的是视觉反馈 + 可访问性支持,所以必须:
立即学习“前端免费学习笔记(深入)”;
- 给目标
<td>动态添加 class(如focused-cell),配合 CSS 高亮 - 同时设置
tabindex="-1",使该单元格可被脚本聚焦(但不进入自然 tab 顺序) - 调用
td.focus()触发focus事件,让屏幕阅读器感知
focus 和 blur 事件在 <td> 上的行为差异
<td> 默认不可聚焦,即使加了 tabindex,它的 focus 事件也不会像 <input> 那样自动触发浏览器默认焦点环——需手动用 CSS 定义 :focus 样式,否则用户看不到任何变化。
另一个易忽略点:鼠标移出时不能只靠 mouseout 清除焦点,因为 mouseout 在子元素间移动也会触发,造成闪烁。应改用 mouseleave 监听 table,并确保只在真正离开表格区域时才 blur():
table.addEventListener('mouseleave', () => {
const focused = document.querySelector('td.focused-cell');
if (focused) {
focused.classList.remove('focused-cell');
focused.blur(); // 移除焦点状态
}
});
键盘导航下如何保持焦点提示一致
仅靠鼠标逻辑不够。用户按 Tab 进入表格后,用方向键移动时,<td> 不会自动获得焦点——必须显式捕获键盘事件,模拟“当前活动单元格”概念。
建议维护一个 currentCell 变量,结合 keydown 处理方向键(ArrowUp/ArrowDown/ArrowLeft/ArrowRight),计算行列索引并聚焦对应 <td>。注意两点:
- 首次 Tab 进入表格时,应自动聚焦第一个
<td>(或带data-start="true"的单元格) - 每次聚焦前先
blur()上一个,再focus()新的,并同步更新focused-cellclass
否则鼠标悬停高亮和键盘导航高亮会错位,破坏一致性。
真实场景里,单元格是否可聚焦、是否跳过空单元格、是否循环滚动,都得按业务逻辑细调——这些边界情况比事件绑定本身更耗调试时间。



















