Angular如何实现一次点击即可从父组件打开子组件的mat-menu
问题根因
该现象是Angular变更检测的执行时机导致的:
- 首次点击按钮时,
changeType方法先将productTitleName赋值为status,此时绑定了*ngIf="productTitleName=='status'"的app-dropdown子组件才会开始初始化渲染 - 你紧接着判断
this.menuData?.clickHoverMenuTrigger时,Angular还未完成子组件的渲染和@ViewChild的实例绑定,this.menuData为undefined,openMenu()不会执行 - 第二次点击时
app-dropdown已经渲染完成,menuData实例存在,所以菜单可以正常打开
解决方案
方案1:手动触发变更检测后打开菜单(推荐)
在赋值后手动触发一轮变更检测,等子组件渲染完成、@ViewChild绑定到实例后再调用打开菜单的方法,修改home.ts代码即可:
// 先从@angular/core导入ChangeDetectorRef import { ChangeDetectorRef } from '@angular/core'; export class HomeComponent { // 注入ChangeDetectorRef实例 constructor(private cdr: ChangeDetectorRef) {} @ViewChild(dropdowncomponent) menuData:dropdowncomponent changeType(name: string) { this.productTitleName = name; // 手动触发变更检测,让子组件完成渲染 this.cdr.detectChanges(); // 此时menuData已有实例,直接打开菜单 if (this.menuData?.clickHoverMenuTrigger) { this.menuData.clickHoverMenuTrigger.openMenu(); } } }
方案2:将*ngIf改为样式隐藏
如果不需要频繁销毁子组件,可以把条件渲染改成样式隐藏,让子组件在页面初始化时就完成渲染,首次点击就能直接拿到实例:
修改home组件模板代码:
<!-- 把*ngIf换成style.display控制隐藏显示 --> <app-dropdown [Title]="productTitleName" (sorting)="triggerSorting($event)" (filtering)="triggerfiltering($event)" [filtersStatusData]="statusFitler" (filteringChangeStatus)="statusChanged($event)" [style.display]="productTitleName==='status' ? 'block' : 'none'"> </app-dropdown>
内容的提问来源于stack exchange,提问作者Kumaravel A
相关产品推荐
相关产品推荐

