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
相关产品推荐
相关产品推荐

