angular - 两个没有父子关系的组件如何通信?

标签 angular angular-material

app.component.ts是我的 Angular 2 应用程序的入口点。它包含两个组件:标题和 sidenav .

@Component({
  selector: 'app-root',
  template: `
    <app-header></app-header>

    <app-sidenav></app-sidenav>
  `
})
export class AppComponent { }

这是我想要实现的:在 <app-header> 中组件 我有一个(菜单)按钮,应该会触发 <app-sidenav> 的打开组件。

换句话说,<app-header> 中按钮的点击事件应该触发 open() <app-sidenav> 中的方法组件。

  • header.component.ts:

    @Component({
      selector: 'app-header',
      template: `
        <button (click)="onSidenavOpen()">Menu</button>
      `
    })
    export class HeaderComponent {
      constructor() { }
    
      onSidenavOpen() {
        // trigger the opening of the <app-sidenav> component
      }
    }
    
  • sidebar.component.ts:

    @Component({
      selector: 'app-sidenav',
      template: `
        <md-sidenav #sidenav>
          // bla bla, sidebar
        </md-sidenav>
      `
    })
    export class SidenavComponent {
      constructor() { }
    
      open(sidenav) {
        sidenav.open();
      }
      close(sidenav) {
        sidenav.close();
      }
    }
    

我读了component interaction section在 Angular 2 文档中,但我正在努力寻找在这两个组件之间进行通信的最佳方法。我的总体意图是为每个组件封装尽可能多的逻辑。

您将如何处理我的用例?你会创建一个中间服务吗?请分享一个例子。

最佳答案

您可以使用服务让两个独立的组件相互通信。在下面的示例中,HeaderComponent 使用 SidebarServicetoggleSideNav 方法将值推送到公开的 ObservableSidenavComponent 在其初始加载时订阅此 Observable 并将响应被推送的新值。

边栏服务:

import { Injectable } from "@angular/core"

import { Observable, Subject } from "rxjs/Rx";

@Injectable()
export class SidebarService {

    private sidenavOpenSubject : Subject<boolean>;

    constructor() {
        this.sidenavOpenSubject = new Subject<boolean>();
    }

    toggleSideNav(opening: boolean): void {
        this.sidenavOpenSubject.next(opening);
    }

    onSideNavToggle(): Observable<boolean> {
        return this.sidenavOpenSubject;
    }

}

标题组件:

@Component({
  selector: 'app-header',
  template: `
    <button (click)="onSidenavOpen()">Menu</button>
  `
})
export class HeaderComponent {
  constructor(private sidebarService: SidebarService) { }

  onSidenavOpen() {
    this.sidebarService.toggleSideNav(true);
  }
}

侧边栏组件:

@Component({
  selector: 'app-sidenav',
  template: `
    <md-sidenav #sidenav>
      // bla bla, sidebar
    </md-sidenav>
  `
})
export class SidenavComponent implements OnInit {
    constructor(private sidebarService: SidebarService) { }

    ngOnInit(): void {
        this.sidebarService.onSideNavToggle().subscribe(
            (opening) => {
                if (opening) {
                    //Logic to open the sidenav here
                } else {
                    //Logic to close the sidenav here
                }
            }
        );
    }

    open(sidenav) {
        sidenav.open();
    }

    close(sidenav) {
        sidenav.close();
    }
}

SidebarService 需要在合适的模块中注册(例如您的 AppModule)。

关于angular - 两个没有父子关系的组件如何通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42279084/

相关文章:

javascript - 从 Angular 2 中的组件设置表单输入值

angular - 我应该在 Angular 2 中使用什么 UI 前端框架

html - 如何使用 Angular Material 创建粘性 header ?

angular - 如何使用 Jasmine 测试 MatSort

node.js - 满足条件时取消所有 Protractor 测试

angular - 使用 Angular 7 实现 ngu-carousel

angular - 服务中的 Apollo GraphQL 查询重复集合项?

Angular 2 : How to use EventEmitter on components created during runtime?

javascript - Angular Material 日期选择器返回 Moment 对象而不是 Date

javascript - md-sidenav Angular Material 防止点击外部关闭