我正在努力提高Angular的水平,我想了解儿童与父母之间交流的最佳做法。我当前要使用的应用程序是在Angular 6上运行的。我知道我可以使用@ ViewChild,@ Output或创建服务在父级组件之间进行通信。还有其他沟通方式吗?如果不是那三者中的哪一个更好,为什么?
这是一个简单的例子:
子HTML
<button (click)="onLinkedClicked();">Click me</button>
儿童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');
}
}
父HTML
<showcase-menu #topNavMenu
[showBranding]="false"
[showSearch]= "false"
(linkedClicked)="linkToggler($event)">.
</showcase-menu>
父级TS
.
.
.
navMenuState: string;
.
.
.
linkToggler($event) {
console.log("partent");
this.navMenuState = $event;
}
答案 0 :(得分:3)
显然,这取决于您想做什么。
@输入
通过使用@Input
,您可以将参数直接传递给子组件。
此外,您通过将一个组件放入另一个组件来耦合组件。
这种方法既有用又简单。
当您要确保将子组件集成到共享特定对象的父组件中并且不必关心同步机制时,这是一种很好的方法。
这意味着,如果更改对象的属性,则对象引用仍然相同,因此会将其更新为父对象和组件。但是,如果在一个组件中更改对象引用(例如,实例化一个新对象或通过远程服务检索一个新对象),则另一个组件将无法检测到对象更改,因此您将出现数据未对齐的情况。
@输出
通过使用@Output
,您将向上发出一个事件,因此,当您想与父级进行交流时,此方法很有用。数据交换是可能的,但这不是事情的重点。
重点是发生了某些事情,例如,在向导中您可以执行某些步骤,并且每个步骤都可以通知父组件该特定步骤已完成。家长不需要知道发生了什么,而只需知道发生了什么,就可以进入下一步。
@ViewChild
通过使用@ViewChild
,您可以将子组件引用引入父组件。
您正在通过混合其逻辑来迫使父级具有特定的子级组件。
当您想将子组件的某些方法调用到父组件中时,这很有用。
使用向导示例,您可以考虑这种情况:
@Output
事件服务
通过使用外部服务,您将数据集中到一个外部对象中,该对象负责管理和更新数据。
对于可以从远程服务中检索数据或可以重新分配数据对象引用的情况,这是一种很好的方法。
此外,通过这种方法,您正在将所有组件彼此分离。他们可以工作,而不必担心别人的行为。
通常Subject
用于服务通信。
您可以找到doc here
主题VS @Output
Subject
使用数据驱动方法。
@Output
使用事件驱动的方法,或者更好的Reactive Programming方法
因此,@Output
是您想要传达事件发生的首选方式,Subject
是传达数据已更改的首选方式。
主题既是可观察值的来源,也是可观察值的来源 本身。您可以像任何可观察的一样订阅主题。
这意味着您可以使用Subject
观察特定的变量或值(Subject
为Observer
),它可以检测到观察到的值变化并发出某种事件。
与此同时,您可以有许多其他观察者通过订阅主题事件来观察Subject
(Subject
为Observable
)。
当受试者观察值改变时,建议所有受试者的订户。
示例可以是票务应用程序。一位用户加载了负责显示剩余剩余空间的组件。他正在考虑选择哪个地方。同时,另一个用户购买了一张票,因此他的位置现在不可用。现在,第一个用户应该看到该位置不可用,因此您需要刷新数据以要求他们访问远程服务(也许使用轮询算法)。检索到新数据后,您会将新数据传递到Subject.next()
中。 Subject
检测到观察值已更改,并通知所有订户该值已更改。显然Subject
将新数据传递给订阅者。
答案 1 :(得分:2)
在您显示的情况下,我更喜欢像您一样使用@Output
。
单击链接不太可能引起广泛关注,因此我认为服务没有意义。
@ViewChild
可以工作,但是会使组件的可重用性降低。如果要在另一个父级中重用子级组件,则必须复制代码。
使用@Output
,如果您想在另一个父级中使用子级组件,则无需复制多余的代码,并且可以非常轻松地绑定到@Output
事件。
答案 2 :(得分:1)
您可以在多个组件之间共享数据
创建服务
import { Injectable } from '@angular/core';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class ChildParentService {
data=new Subject();
constructor() { }
}
答案 3 :(得分:0)
在以下情况下使用父母与子女之间的服务通信:
1。您想要将数据从父组件传递到多个子组件。
2。多个子组件具有相同的EventEmitter,它将被分派到父组件。