Angular - @Input 和@Output 与可注入(inject)服务

标签 angular typescript design-patterns dependency-injection

我在问自己 @Input/@Output 在父/子组件中的区别在哪里一旦使用依赖注入(inject)@Injectable() 实例化。或者除了 Input/Output can only be used in 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;
}

依赖注入(inject)

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

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

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

}

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

@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 非常困惑和笨拙。

最佳答案

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

@Input@Output 如果父子之间的通信只是父子之间的通信,则很有用。拥有仅维护 2 个组件(或无论祖父 -> 父 -> 子组件嵌套有多深)的单例数据的服务是没有意义的。

如果您的 parent 需要对 child 的变化使用react,它们也很有用。例如,单击子组件中的按钮调用父组件中的函数:

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

在父级中:

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

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

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

然后你可以将定义传递给你的 child ,这是从 parent 那里设置的:

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

那么你的子组件可能有:

@Input properties: MyChildProperties;

你的模板变成了:

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

您的 child 可以从 properties.propertyproperties.anotherProperty 等访问这些属性

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

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

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

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

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

关于Angular - @Input 和@Output 与可注入(inject)服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51027711/

相关文章:

angular - 调用函数时清除 Observable 值

reactjs - 将 TypeScript 模块从本地模块导入 React 应用程序

java - 数据模型应该包含 Controller 吗? (MVC)

Angular 9 + CLI (TypeScript) - 如何停止生成 .spec.ts 测试文件

javascript - Moment.js 在 Mozilla Firefox 中显示无效日期

angular - appModule : StaticInjectorError(AppModule)[BASE_URL]: 中的 NullInjection 错误

typescript - 如何在 typescript 中正确使用lodash-es?

typescript - 类中的枚举(TypeScript 定义文件)

javascript - 我应该/必须导出 Javascript ES6 中另一个导出类返回的返回类吗?

c++ - 哪种设计模式便于维护数据文件的向后兼容性?