启用 delegatesFocus: true 可解决键盘聚焦断裂问题,需在 attachShadow 时声明且不可后期修改,内部须有唯一可聚焦元素,并手动同步 :focus 状态以支持无障碍。
直接启用 delegatesFocus: true 就能解决大部分键盘聚焦断裂问题——它让外部点击或 Tab 导航自动落到 Shadow DOM 内第一个可聚焦元素上,无需手动调用 focus() 或监听事件做中转。但“异步优化”不是指延迟聚焦,而是指在组件动态加载、条件渲染或嵌套层级较深时,确保焦点委托行为稳定触发、状态同步及时、不被生命周期打断。
该选项不可后期补设,也不能通过属性动态切换。一旦 shadow root 创建完成,delegatesFocus 值即锁定:
this.attachShadow({ mode: 'open', delegatesFocus: true })
const shadow = this.attachShadow({ mode: 'open' }); shadow.delegatesFocus = true(无效)connectedCallback 中反复调用 attachShadow(会报错或覆盖已有 shadow)浏览器只在首次聚焦时查找第一个可聚焦元素。若组件结构异步生成(如 slot 内容延后插入、if 条件块初始为空),可能造成委托失败:
<input tabindex="0"> 或 <button tabindex="0">,比依赖 autofocus 更可靠tabindex="0",否则行为不可预测<input>),需在插入后手动触发一次 input.focus(),但仅限首次;后续仍靠 delegatesFocus 自动接管仅开启 delegatesFocus 不足以支撑视觉反馈和逻辑判断。宿主元素本身不会自动获得 :focus 状态,必须手动映射:
<input> 上监听 focus 和 blur 事件this.toggleAttribute('focused', e.type === 'focus')
:host([focused]) { outline: 2px solid #0078d4; } 实现无障碍轮廓focusin/focusout 到宿主上——这些事件不穿透 shadow boundary当自定义组件层层包裹(如 <my-form> → <my-field> → <my-input>),焦点委托仍有效,但需注意:
delegatesFocus: true,否则焦点会在某一层卡住mode: 'closed',则无法通过 JS 访问 shadow 内部,调试困难;生产环境可用,但开发阶段建议保持 'open'