视图完全加载后如何从另一个组件调用方法(AppComponent)?

Posted

技术标签:

【中文标题】视图完全加载后如何从另一个组件调用方法(AppComponent)?【英文标题】:How to call a method from another component after view is fully loaded (AppComponent)? 【发布时间】:2019-01-17 02:52:15 【问题描述】:

我在 HeaderComponent 中使用来自 Angular Material 的 MatMenu。我只需要在特定条件下(方法)打开菜单,在ProductDetailComponent上调用这个方法。但是这个方法只在 ngAfterViewInit() 内部起作用,在视图加载之后。

我找到了一种从ProductDetailComponentHeaderComponent 的通信方式,但是有一个子父关系可以到达组件。 HeaderComponent 是从 AppComponent 调用的。

这里是应用组件

<my-header [openMenu]="clickBehavior"></my-header>
<router-outlet></router-outlet> <!-- ProductComponent -->

产品组件

&lt;router-outlet&gt;&lt;/router-outlet&gt; &lt;!-- ProductDetailComponent --&gt;

ProductDetail组件

export class ProductComponent 
  clickBehavior = new BehaviorSubject(null);

  click() 
    this.clickBehavior.next(1);
  

ProductDetail 标记

<!-- i need to move it to app component 
<my-header [openMenu]="clickBehavior"></my-header>
-->
<div>
  <button (click)="click()">Click</button>
</div>

标题组件

export class HeaderComponent implements AfterViewInit 
  @ViewChild('trigger') trigger: MatMenuTrigger;
  @Input() openMenu: Observable<any>;

  ngAfterViewInit() 
    this.openMenu.subscribe(value => 
      if (value) 
        this.trigger.openMenu();
      
    );
  

标题标记

<button mat-button
        [matMenuTriggerFor]="menu"
        #trigger="matMenuTrigger">Menu
</button>
<mat-menu #menu="matMenu">
  <button mat-menu-item>Item 1</button>
  <button mat-menu-item>Item 2</button>
</mat-menu>

【问题讨论】:

你可以在stackblitz.com中添加你的代码 我想实现这个link,但是在AppComponent上使用这个结构&lt;my-header [openMenu]="clickBehavior"&gt;&lt;/my-header&gt; &lt;router-outlet&gt;&lt;/router-outlet&gt; 【参考方案1】:

您可以通过使用共享服务并在需要的地方注入服务来实现此目的。

设置一个共享服务,我设置了获取、设置和切换菜单状态的方法。

SharedService.ts

import  Injectable  from '@angular/core';

    @Injectable()
    export class SharedService 

    //The current menu state
    private showMenu_ = false;

    //get the current menu state
    get showMenu() 
        return showMenu_;
    

    //set the menu state
    set showMenu(state: boolean) 
        this.showMenu_ = state;
    

    //toggle the menu
    public toggleMenu() 
        this.showMenu_ = !this.showMenu;
    



将服务注入到 appComponent 中,这样我们就可以用它来控制菜单状态。

appComponent.ts

import  SharedService  from 'PATH TO SHARED SERVICE';

...

constructor(public sharedService: SharedService)

根据 sharedService 中设置的状态设置 my-header 以显示/隐藏。

appComponent.html

<my-header *ngIf="sharedService.showMenu"></my-header>

将服务注入任何其他组件/页面以更改菜单的状态。 在本例中为 ProductComponent.ts。

ProductComponent.ts

import  SharedService  from 'PATH TO SHARED SERVICE';

...

constructor(public sharedService: SharedService)

ProductComponent.html

<div>
  <button (click)="sharedService.toggleMenu()">Click</button>
</div>

或使用服务中的 BehavourSubject。

在 SharedService 中创建 BehaviorSubject。

import  Injectable  from '@angular/core';

@Injectable()
export class SharedService 

//The current menu state
private showMenu_ = false;
private showMenu$: BehaviorSubject<boolean> = new 
BehaviorSubject(false);

//get a reference to showMenu$ for subscription
public menuState() 
    return showMenu$;


//Change menu state to show.
public showMenu()
    this.showMenu_ = true;
    this.showMenu$.next(this.showMenu_);


//Change menu state to hide.
public hideMenu()
    this.showMenu_ = false;
    this.showMenu$.next(this.showMenu_);


//Toggle menu state.
public toggleMenu()
    this.showMenu_ = !this.showMenu;
    this.ShowMenu$.next(this.showMenu_);


//get the current menu state.
public getMenuState() 
    return this.showMenu$.getValue();

将服务注入到 appComponent 中,以便我们可以订阅菜单状态。

appComponent.ts

import  SharedService  from 'PATH TO SHARED SERVICE';

...

export class appComponent implements OnInit, OnDestroy 

//variable used to show/hide the menu.
public showMenu;

//reference to subscription so we can unsubscribe later.
private this.menuStateSub: Subscription;

constructor(public sharedService: SharedService)

ngOnInit()   
    //subscribe to the menuState BehaviorSubject
    this.menuStateSub = this.sharedService.menuState().subscribe((state)=>
        this.showMenu = state;
    )


ngOnDestroy() 
    //unsubscribe before leaving the page
    this.menuStateSub.unsubscribe();

根据 sharedService 中设置的状态设置 my-header 以显示/隐藏。

appComponent.html

<my-header *ngIf="sharedService.showMenu"></my-header>

最后在我们需要控制菜单状态的地方注入服务。

ProductComponent.ts

import  SharedService  from 'PATH TO SHARED SERVICE';

...

constructor(public sharedService: SharedService)

现在我们可以使用该服务来切换状态。 ProductComponent.html

<div>
  <button (click)="sharedService.toggleMenu()">Click</button>
</div>

【讨论】:

以上是关于视图完全加载后如何从另一个组件调用方法(AppComponent)?的主要内容,如果未能解决你的问题,请参考以下文章

iPad拆分视图调用/从另一个视图加载

使用标签栏从另一个视图返回时如何重新加载视图控制器

如何快速从另一个视图控制器重新加载表格视图

从 Vue.js 中的另一个组件调用方法

如何从另一个类调用 QMainWindow 组件?

ReactJS - 从另一个组件调用一个组件方法