You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中focusout事件内document.activeElement始终返回body问题

问题根因

focusout 属于冒泡类失焦事件,触发时点处于原元素已失焦、新目标元素尚未完成聚焦的空窗期,此时document.activeElement会临时指向body元素。你切到其他窗口/打断点的操作刚好等待了聚焦流程完成,所以才能拿到正确的activeElement值。

解决方案

推荐方案:使用FocusEvent自带的relatedTarget属性

该属性会直接返回即将获得焦点的目标元素,完全规避时序问题,不需要依赖document.activeElement。

修改后代码如下:

component.html

<button 
  (focusout)="_onFocusOut($event)" 
  class="typography-button" (keydown)="_onItemKeyDown($event)" 
  (click)="_selectItem(item)" #menuitem>
  {{ item.label }}
</button>

component.ts

_onFocusOut(event: FocusEvent): void{
  // relatedTarget 即为即将获得焦点的元素
  const isActiveElement = this.menuItemElements?.toArray().some(item => {
    return item.nativeElement == event.relatedTarget;
  });

  if(!isActiveElement){
    // 执行原逻辑
  }
}

兼容方案:延迟获取activeElement

如果确实需要使用document.activeElement做判断,可以用setTimeout把判断逻辑放到宏任务队列,等待当前聚焦流程执行完成后再取值:

_onFocusOut(): void{
  setTimeout(() => {
    const isActiveElement = this.menuItemElements?.toArray().some(item => {
      return item.nativeElement == document.activeElement;
    });

    if(!isActiveElement){
      // 执行原逻辑
    }
  }, 0)
}

注意:该方案需要额外处理组件销毁逻辑,避免延迟执行期间组件销毁导致的潜在问题。


内容的提问来源于stack exchange,提问作者ToneyPK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 04:06:03