delegatesfocus对输入类组件特别重要,因其使外部点击或tab导航自动聚焦shadow dom内首个可聚焦元素,确保键盘操作连贯与屏幕阅读器可识别,且须在attachshadow时声明、配合内部焦点监听与宿主状态同步。

直接启用 delegatesFocus 就能显著改善键盘用户对自定义输入组件的聚焦体验——它让外部点击或 Tab 导航自动落到 Shadow DOM 内部第一个可聚焦元素上,无需手动管理焦点逻辑。
为什么 delegatesFocus 对输入类组件特别重要
自定义输入组件(比如带图标的搜索框、带清空按钮的文本框)通常把原生 <input> 封在 Shadow DOM 里。默认情况下,用户点击组件空白区域或按 Tab 键时,焦点不会进入内部 input,导致键盘操作中断、屏幕阅读器无法识别可交互区域。
启用 delegatesFocus: true 后,浏览器会自动将焦点委托给 shadow 内第一个 tabindex="0" 或原生可聚焦元素(如 <input>、<button></button>),行为与原生表单控件一致。
正确设置 delegatesFocus 的方式
必须在创建 shadow root 时传入,不能后期修改:
- 使用
attachShadow({ mode: 'open', delegatesFocus: true }) - 确保 shadow 内至少有一个可聚焦元素(例如
<input autofocus>或显式设置tabindex="0") - 避免在 shadow 中多个元素同时设
autofocus,否则委托行为不可预测
配合 focus 状态样式的联动处理
仅开启 delegatesFocus 不够,还需让宿主元素响应内部聚焦状态变化:
- 在 shadow 内
<input>上监听focus和blur事件 - 在事件处理器中通过
this.setAttribute('focused', '')或this.toggleAttribute('focused')更新宿主属性 - 用 CSS 的
:host([focused])为宿主添加轮廓、阴影等视觉反馈
常见误区与规避建议
不要依赖 focusin/focusout 事件捕获宿主聚焦:这些事件不穿透 shadow boundary,必须监听内部元素事件并手动同步状态。
避免关闭 delegatesFocus 后自行调用 input.focus():这会破坏原生 Tab 顺序,且无法保证屏幕阅读器正确播报。
模态框、下拉菜单等复杂组件务必启用该选项:否则键盘用户无法进入内容区,违反 WCAG 2.1 标准中的“键盘可操作”要求。











