Angular2 - 使用服务的组件之间的交互

Angular2 - Interaction between components using a service

我有两个组件 A 和 B,其中组件 A 包含一个按钮。我希望当用户点击这个按钮时,在组件 B

上触发一个函数
<A></A>
<router-outlet></router-outlet>

并且组件 B 是使用 routing.I 呈现的,我正在考虑使用具有可观察布尔值的服务,该值指示 A 中的按钮是否被单击。这是实现它的正确方法吗?

Angular 服务

您必须使用服务在您的两个组件之间进行通信。

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

您的服务有一个 属性 事件。所以组件 A 可以发出事件,组件 B 可以订阅它。

使用 RxJS 发出和订阅您的事件。

If my answer does not satisfy you. Please tell me and I will work on it.

共享服务是 non-related 组件之间的一种常见通信方式。 您的组件需要 ,因此请确保它在根级别提供。

使用 的示例:

共享服务:

@Injectable()
export class SharedService {

    isVisibleSource: BehaviorSubject<boolean> = new BehaviorSubject(false);

    constructor() { }
}

组件 1:

export class Component1 {

    isVisible = false;

    constructor(private sharedService: SharedService) { }

    onClick(): void {
        this.isVisible = !this.isVisible;
        this.sharedService.isVisibleSource.next(this.isVisible);
    }
}

组件 2:

export class Component2 {

    constructor(private sharedService: SharedService) { }

    ngOnInit(): void {
        this.sharedService.isVisibleSource.subscribe((isVisible) => {
            console.log('isVisible: ', isVisible); // => true/false
        });
    }
}

值得一提的是,BehaviorSubject 在订阅后 returns 它持有的最后一个值,因此上例中的组件将在实例化后立即更新为最新值。

BehaviorSubject 甚至无需订阅它也可以获取其最新值:

this.sharedService.isVisibleSource.getValue(); // => true/false

停止使用组件交互服务!!!

服务在编程中是一个无状态的概念,它只能依靠输入和其他注入的服务来产生它的输出。在服务中存储数据(尽管有效)是反模式(因为您的服务现在是有状态的)。

您可以通过绑定组件的@Input() 和@Output() 来实现您所需要的:

//main container html
<A></A>
<router-outlet (activate)="onRouterOutletActivate($event)"></router-outlet>

//main container ts
@ViewChild(ComponentA, {static: false}) a : ComponentA;
onRouterOutletActivate(event: ContainerOfB): void {
    this.activeRouteComponent = event;
    // make sure doStuff method is defined public in ComponentB
    // clickOutput is an @Output() on ComponentA which propagates click event
    this.a.clickOutput.subscribe(() => this.activeRouteComponent.b.doStuff());
}

//ContainerOfB, the container that has B in it
@ViewChild(ComponentB, {static: false}) b : ComponentB;

//ComponentA html
<button (click)="callback()">button</button>

//ComponentA ts
@Output() clickOutput: EventEmitter<void> = new EventEmitter<void>()
callback() { this.clickOutput.emit(); }

您还可以实现异步性和反应性,这通过在 Angular 的核心中使用 rxjs 得到了强烈强调(而使用服务方法则不会)。

我知道组件通信的共享服务没有上述方法那么复杂,但仅仅因为它有效并不意味着您应该这样做。如果您的梅赛德斯被锁在门外,您更愿意做什么:打破 window 玻璃并打开门锁,或者叫锁匠过来打开它。

p.s。 Angular 是涂料因此比喻(梅赛德斯)