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方法的执行逻辑。
- 在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方法'); } }
- 确保
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
相关产品推荐
相关产品推荐

