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

Angular下拉菜单子项点击事件与focusout事件冲突,setx方法未触发求助

Angular自定义下拉菜单:点击子项时触发setx而非focusout的set方法

当点击下拉菜单的menu-item子项时,浏览器事件触发顺序是先执行dropdown的focusout事件,再执行menu-item的click事件。如果focusout绑定的set方法执行了关闭下拉、修改状态等操作,会导致后续click事件被中断,最终出现set重复触发而setx不执行的问题。

以下是几种可行的解决方案:

解决方案1:通过relatedTarget判断焦点是否转移到子元素

在set方法中,利用FocusEvent的relatedTarget属性,检查失去焦点后焦点是否落在dropdown的子元素上。如果是,则跳过set方法的执行逻辑。

  1. 在dropdown组件中注入ElementRef,用于获取组件的DOM元素:
import { Component, ElementRef } from '@angular/core';

@Component({
  selector: 'dropdown',
  templateUrl: './dropdown.component.html'
})
export class DropdownComponent {
  constructor(private elementRef: ElementRef) {}

  set(event: FocusEvent) {
    // 检查焦点是否转移到当前组件的子元素上
    if (event.relatedTarget && this.elementRef.nativeElement.contains(event.relatedTarget as Node)) {
      return; // 跳过set方法逻辑
    }
    // 你的原set方法业务逻辑
    console.log('执行set方法');
  }
}
  1. 确保menu-item元素可被聚焦(添加tabindex属性),这样relatedTarget才能正确识别:
<menu-item *ngFor="let val of values" tabindex="0" (click)="setx(val)">
  {{val}}
</menu-item>

解决方案2:通过状态标记跳过focusout逻辑

在父组件中维护一个状态变量,标记是否点击了menu-item,让set方法根据状态决定是否执行。

// 父组件代码
isItemClicked = false;

set(event: FocusEvent) {
  if (this.isItemClicked) {
    this.isItemClicked = false; // 重置状态
    return;
  }
  // 原set方法逻辑
}

setx(val: any) {
  this.isItemClicked = true;
  // 你的setx业务逻辑
  console.log('执行setx方法,值为:', val);
}

解决方案3:延迟执行focusout逻辑(备选方案)

利用setTimeout延迟set方法的执行,让click事件先触发:

set(event: FocusEvent) {
  setTimeout(() => {
    // 原set方法逻辑
    console.log('执行set方法');
  }, 100); // 延迟100ms确保click先执行
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:27:41