【问题标题】:Angular - @Input and @Output vs. Injectable ServiceAngular - @Input 和 @Output 与可注入服务
【发布时间】:2018-06-25 16:07:31
【问题描述】:

我在问自己,父/子组件中的@Input/@Output 和 使用仅通过依赖注入@Injectable() 启用一次的服务之间的区别在哪里。或者除了 Input/Output 只能在 parent-/child-comp 中使用之外还有什么区别。

以下示例以获得更好的可视化:

使用@Input:

<parent-comp>
   <child-comp [inputFromParent]="valueFromParent"></child-comp>
</parent-comp>

子组件:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  @Input() public inputFromParent: string;
}

依赖注入

@Injectable()
export class Service {
   private value: string;

public get value(): string {
   return value;
}

public set value(input): void {
   value = input;
}

}

现在我们可以在父组件中设置值。并通过依赖注入获取子组件中的值。 子组件:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  private value: string;
  constructor(private service: Service) {
  this.value = this.service.getValue;
}

}

尽管第一种方法看起来更简单,但我认识到使用 3-4 个属性通过父/子组合进行。使用@Input/@Output 会使 tamplete 变得非常混乱和笨拙。

【问题讨论】:

  • 使用服务更加灵活,因为它使用@Injectable() 装饰器创建服务的单例实例,并且可以将其注入任何组件中,甚至可以注入到另一个服务中。
  • 我倾向于避免为了灵活性而牺牲正确性。

标签: angular typescript design-patterns dependency-injection


【解决方案1】:

不完全是一个有明确答案的问题,但是....

@Input@Output 在父母和孩子之间的交流只是这样的情况下很有用,在父母和孩子之间。拥有一个只为 2 个组件维护单例数据的服务(或者无论祖父组件 -> 父组件 -> 子组件嵌套多么深)是没有意义的。

如果您的父母需要对孩子的变化做出反应,它们也很有用。例如,单击子组件中的按钮调用父组件中的函数:

<my-child-component (myOutputEmitter)="reactToChildChange($event)"></my-child-component>

在父级中:

reactToChildChange(data: any) {
  // do something with data
}

如果您发现自己将许多@Input 属性传递给一个孩子,并且想要整理一个模板,那么您可以为输入定义一个接口,然后将其传递。例如

export interface MyChildProperties {
   property?: any;
   anotherProperty?: any;
   andAnotherProperty?: any;
}

然后您可以将定义传递给您的孩子,该定义是从父级设置的:

childProperties: MyChildProperties = {
    property: 'foo',
    anotherProperty: 'bar',
    andAnotherProperty: 'zoob'
}

那么你的子组件可能有:

@Input properties: MyChildProperties;

你的模板变成:

<my-child-component [properties]="childProperties"></my-child-component>

您的孩子可以通过properties.propertyproperties.anotherProperty 等访问这些属性。

干净、整洁,您的数据现在包含在那些需要通信的组件中。

但是,当多个组件需要访问整个应用程序中的读/写数据时,应该使用服务。例如,考虑UserService,其中许多不同的组件需要能够访问当前登录的用户。在这种情况下,服务是明智的,因为它是一个单例,所以一旦你设置了登录用户,任何注入 UserService 的组件都可以访问它的数据和功能。

类似地,如果您要使用服务来响应更改,那么您会发现自己使用可观察对象编写服务,以便您的组件可以订阅数据中的更改。如上所示,Eventemitters 已经通过@Output 为您提供了这种模式。

如果是简单的父->子通信,这是不必要的开销,应该避免。

也就是说,如果您发现自己使用服务来管理全局状态,那么最好使用某种形式的状态管理,例如 ngrx

【讨论】:

  • 优秀的答案。谢谢!
  • 不错的答案,但我会用另一种情况来完成它,服务可以用于简单的父/子通信:如果您需要存储状态并在加载另一个组件时保存它(请更正如果我错了,我)。
猜你喜欢
  • 2018-11-17
  • 2019-09-17
  • 1970-01-01
  • 2016-04-25
  • 2017-05-10
  • 2020-12-18
  • 1970-01-01
  • 2014-09-19
  • 2019-10-30
相关资源
最近更新 更多