paint-brush
如何使用 Angular @Input 将数据传递给动态创建的组件经过@briantreese
379 讀數
379 讀數

如何使用 Angular @Input 将数据传递给动态创建的组件

经过 Brian Treese4m2024/02/27
Read on Terminal Reader

太長; 讀書

Angular 16 允许您在动态创建的组件之间从父组件传递数据到子组件。以前,我们必须在父组件中提供信息,然后将其注入到子组件中。现在,我们可以使用“@Input”装饰器来做到这一点。
featured image - 如何使用 Angular @Input 将数据传递给动态创建的组件
Brian Treese HackerNoon profile picture

如果您在 Angular 中使用动态创建的组件,您可能会发现在需要时在父组件和子组件之间传递信息很困难。您需要在父组件中提供信息,然后将其注入子组件中。虽然这并不一定很难做到,但它会产生大量额外的样板代码。


如果我们能够像我们习惯的那样使用@Input装饰器,那就好多了。嗯,你猜怎么着?从版本 16 开始,Angular 支持执行此操作。在这篇文章中,我将向您展示如何操作。好吧,让我们开始吧。

使用角度注入器以旧方式传递数据

首先,让我们看看如何将数据从父组件传递到动态创建的组件。在此示例中,在组件模板中,我们有*ngComponentOutlet ,并将其传递给播放器组件。


在本例中,我们还传递了一个自定义子注入器,这就是我们之前为子组件注入数据的方式。

主要.ts

 @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 核心的注入方法来设置玩家属性。

玩家组件.ts

 export class PlayerComponent { protected player?: Player = inject(PlayerToken); }


所以,所有这一切只是将一个简单的玩家对象传递给动态组件。我的意思是,如果这不是动态组件,我们只需将其设为@Input并将玩家数据对象绑定到父级中的@Input即可。但这是动态创建的组件,所以我们不能这样做,对吧?


好吧,从 Angular 16 开始,我们实际上可以使用@Input来代替,而且它比我们迄今为止看到的要简单得多。

使用*ngComponentOutlet输入对象以新方式传递数据

我们首先将此玩家属性更改为@Input 。并且,只需将其输入到我们的播放器界面中即可。

玩家组件.ts

 export class PlayerComponent { @Input() player?: Player; }


现在,我们可以删除注入方法和玩家令牌导入,因为不再需要它们。然后,回到父级模板中,我们可以删除注入器,并将其替换为输入对象。我们可以在任意数量的输入上传递这个对象。因此,如果我们有五个输入,我们只需包含它们的名称,然后向每个输入传递我们需要的任何数据。


但在这种情况下,我们的子组件玩家只有一个输入,所以这就是我们需要传递的全部内容。

主要.ts

 @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 示例中查看这些技术的演示代码和示例。如果您有任何问题或想法,请随时发表评论。