如果您在 Angular 中使用动态创建的组件,您可能会发现在需要时在父组件和子组件之间传递信息很困难。您需要在父组件中提供信息,然后将其注入子组件中。虽然这并不一定很难做到,但它会产生大量额外的样板代码。
如果我们能够像我们习惯的那样使用@Input
装饰器,那就好多了。嗯,你猜怎么着?从版本 16 开始,Angular 支持执行此操作。在这篇文章中,我将向您展示如何操作。好吧,让我们开始吧。
首先,让我们看看如何将数据从父组件传递到动态创建的组件。在此示例中,在组件模板中,我们有*ngComponentOutlet
,并将其传递给播放器组件。
在本例中,我们还传递了一个自定义子注入器,这就是我们之前为子组件注入数据的方式。
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; injector: childInjector"></ng-container> ` }) export class App { protected playerComponent = PlayerComponent; }
为了创建这个子注入器,我们需要创建一个属性,以便可以在模板中设置并使用它。
export class App { protected childInjector?: Injector; ... }
然后,我们需要从构造函数内的角度核心注入注入器。
export class App { ... constructor(private injector: Injector) { } }
之后,我们需要使用 create 方法和提供者数组设置子注入器,以将玩家令牌提供给子注入器。
export class App { ... constructor(private injector: Injector) { this.childInjector = Injector.create({ providers: [ { provide: PlayerToken, useValue: this.player } ], parent: this.injector }); } }
最后,在子组件(我们的玩家组件)中,我们需要使用 Angular 核心的注入方法来设置玩家属性。
export class PlayerComponent { protected player?: Player = inject(PlayerToken); }
所以,所有这一切只是将一个简单的玩家对象传递给动态组件。我的意思是,如果这不是动态组件,我们只需将其设为@Input
并将玩家数据对象绑定到父级中的@Input
即可。但这是动态创建的组件,所以我们不能这样做,对吧?
好吧,从 Angular 16 开始,我们实际上可以使用@Input
来代替,而且它比我们迄今为止看到的要简单得多。
*ngComponentOutlet
输入对象以新方式传递数据我们首先将此玩家属性更改为@Input
。并且,只需将其输入到我们的播放器界面中即可。
export class PlayerComponent { @Input() player?: Player; }
现在,我们可以删除注入方法和玩家令牌导入,因为不再需要它们。然后,回到父级模板中,我们可以删除注入器,并将其替换为输入对象。我们可以在任意数量的输入上传递这个对象。因此,如果我们有五个输入,我们只需包含它们的名称,然后向每个输入传递我们需要的任何数据。
但在这种情况下,我们的子组件玩家只有一个输入,所以这就是我们需要传递的全部内容。
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; inputs: { player }"></ng-container> ` })
现在,我们可以删除子注入器。这意味着我们也可以完全删除构造函数。最后,我们可以从角度核心和玩家令牌导入中删除注入器,因为我们不再使用它们。
export class App { protected player: Player = { name: 'LeBron James', games: 1421, points: 38652, fieldGoalPercentage: 0.505, threePointPercentage: 0.345, imageName: 'lebron-james' }; protected playerComponent = PlayerComponent; }
就是这样。我们可以看到一切都像以前一样进行。因此,更容易实现,代码也更少,这总是很棒的。
但令人遗憾的是,虽然支持@Input
,但不支持@Output
。有点无赖,但事实就是如此。希望他们将来会增加支持,因为这也非常方便,但我们只能拭目以待。
在下面的 Stackblitz 示例中查看这些技术的演示代码和示例。如果您有任何问题或想法,请随时发表评论。