child parent Angular 中的沟通最佳实践

child parent communication best practices in Angular

我正努力在 Angular 方面做得更好,我想知道 child-parent 沟通之间的最佳实践。我当前要使用的应用程序是 Angular 6。我知道我可以使用 @ViewChild、@Output 或创建服务在 child-parent 组件之间进行通信。是否有另一种方式进行通信?如果不是,这 3 个中哪个更好,为什么?

这是一个简单的例子:

Child HTML

<button (click)="onLinkedClicked();">Click me</button>

Child TS

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
.
.
.
export class showcaseMenuComponent implements OnInit {
    @Output() public linkedClicked = new EventEmitter<String>();

    constructor() {}

    onLinkedClicked() {
        console.log('on click child');
        this.linkedClicked.emit('collapsed');
    }
}

Parent HTML

<showcase-menu #topNavMenu 
               [showBranding]="false"
               [showSearch]= "false"  
               (linkedClicked)="linkToggler($event)">. 
</showcase-menu>

Parent TS

.
.
.
 navMenuState: string;
.
.
.
  linkToggler($event) {
    console.log("partent");
    this.navMenuState = $event;
  }

在您所展示的情况下,我更愿意像您那样使用 @Output

点击 link 不太可能引起广泛关注,因此我认为服务没有意义。

@ViewChild 可以工作,但它会降低组件的可重用性。如果你想在不同的父组件中重用子组件,你必须复制代码。

使用@Output,如果你想在不同的父组件中使用子组件,不需要复制额外的代码,你可以很容易地绑定到@Output事件。

您可以在多个组件之间共享数据

创建服务

 import { Injectable } from '@angular/core';
    import {Subject} from 'rxjs/Subject';    
    @Injectable()
    export class ChildParentService {

     data=new Subject();
      constructor() { }

    }

示例:https://stackblitz.com/edit/child-to-parent-bntt2h

显然这取决于你想做什么。

@Input

通过使用 @Input,您可以直接将参数传递给子组件。 此外,您通过将一个组件放在另一个组件中来耦合组件。 这种方法既有用又简单。

当您要确保将子组件集成到共享特定对象的父组件中并且您不必关心同步机制时,这是一种很好的方法。

也就是说,如果你改变了对象的一个​​属性,对象的引用还是一样的,所以更新为parent和component。但是,如果您在一个组件中更改对象引用(例如实例化一个新对象或通过远程服务检索新对象),另一个组件将无法检测到对象更改,因此您将出现数据错位。

@Output

通过使用 @Output,您将向上发出一个事件,因此当您想要向父级传达某事已发生时,此方法很有用。数据交换是可以的,但不是重点

重点是发生了什么事,例如在向导中您可以有一些步骤,每个步骤都可以通知父组件该特定步骤已完成。 Parent 不需要知道发生了什么,只要发生了就可以进行下一步。

@ViewChild

通过使用 @ViewChild,您可以将子组件引用到父组件中。

您通过混合他们的逻辑来强制父组件让特定的子组件工作。

当你想在父组件中调用子组件的某些方法时,这很有用。

使用精灵例子你可以想到这种情况:

  • 我们有 3 个步骤
  • 第三步完成并向父级发出 @Output 事件
  • 父级捕获事件并尝试保存数据
  • data saving ok => parent 告诉最后一步组件显示成功消息 或
  • 数据保存失败 => 父级告诉最后一步组件显示失败消息

服务

通过使用外部服务,您可以将数据集中到一个负责管理和更新数据的外部对象中。

对于可以从远程服务检索数据或可以重新分配数据对象引用的情况,这是一种很好的方法。

此外,通过这种方法,您可以将所有组件彼此解耦。他们可以工作而不用担心别人的行为。

一般Subject用于服务通讯。

你可以找到doc here

主题 VS @Output

Subject 使用数据驱动方法。 @Output 使用事件驱动方法,或者更好的 Reactive Programming 方法

因此,同时 @Output 是您想要传达事件已发生的首选方式,Subject 是传达数据已更改的首选方式。

A Subject is both a source of observable values and an Observable itself. You can subscribe to a Subject as you would any Observable.

这意味着您可以使用 Subject 来观察特定的变量或值(Subject as Observer),它会检测观察到的值变化并发出某种事件。

与此同时,您可以让许多其他观察者通过订阅对象的事件来观察 SubjectSubject 作为 Observable)。

当对象观测值发生变化时,建议所有对象的订阅者。

票务应用程序就是一个例子。一位用户加载负责显示空闲剩余位置的组件。他正在考虑选择哪个地方。与此同时,另一个用户买了票,所以他的位置现在不可用。第一个用户现在应该看到那个地方不可用,所以你需要刷新数据要求他们远程服务(可能使用轮询算法)。当检索到新数据时,您将新数据传递到 Subject.next()Subject 检测到观测值发生了变化,并通知他的所有订阅者该值发生了变化。显然 Subject 将新数据传递给订阅者。

在以下情况下使用父子之间的服务通信:

1.You想将数据从父组件传递给多个子组件。

2.Several 子组件具有将分派给父组件的相同 EventEmitter。