利用Angular的依赖注入功能让你的父母获得自由
[
11月4日 - 3分钟阅读
来源。Freepik
如果你正在使用一个模块化、组件驱动的架构,你将面临的最大挑战之一是如何实现父子组件/指令之间的沟通。一方面,你希望每个组件/指令都能独立地专注于它们的目的。另一方面,你需要它们一起工作,就像它们是作为一个有凝聚力的单元建立的。
幸运的是,Angular为任何类型的情况都提供了你所需要的东西
如果你的父视图包含了子视图,一个常见的方法是使用@Input()和@Output()装饰器。为了与父视图通信,你可以通过子视图发出自定义事件。为了与子代沟通,你可以传递与父代绑定的属性。
你也可以使用@ViewChild/@ViewChildren和@ContentChild/@ContentChildren来打破父/子间的隔阂。(我将在以后的文章中讨论这些强大的装饰器)。)
如果你的父视图不直接包含子视图,或者根本不存在任何关系,你可以在服务中使用观测器来交流数据。这样一来,实际的关系并不重要,因为任何注入服务的人都可以更新和订阅观察者。
为什么使用依赖注入来寻找父类
我创建了一个任务系统,在一个表行组件中显示每个任务。我还创建了按钮组件来对表行进行操作。然而,我不想把按钮组件包含在表行组件中,这样它们就可以被使用,不管它们是否在表中。
我面临的问题是如何给按钮组件分配一个特定的ID,而不需要一次又一次地把ID作为一个输入来传递。例如,这里是表行组件的HTML,它在一个任务数组上进行迭代。
<ces-table-row *ngFor="let task of tasks; let index = index;" [id]="task.id" [index]="index"> <ces-table-column class="justify-center"> <ces-view-pin [active]="task.pinned"></ces-view-pin> <ces-view-delete></ces-view-delete> </ces-table-column> <ces-table-column class="justify-center">{{ task.id }}</ces-table-column> <ces-table-column class="justify-center"> <ces-task-menu-statuses [default]="task.status"></ces-task-menu-statuses> </ces-table-column> <ces-table-column>{{ task.dateUpdated | date: 'short' }}</ces-table-column> <ces-table-column>{{ task.title }}</ces-table-column> <ces-table-column>{{ task.notes }}</ces-table-column></ces-table-row>
我提到的按钮组件使用选择器 "ces-view-pin "和 "ces-view-delete"。我希望这些组件只负责按钮的交互状态,并在它们被按下时向一个服务发送一个消息。这样,我就可以避免每次使用它们时重复多余的代码,而且无论谁在使用它们,它们的行为都是一样的。
由于表行组件正在获取任务ID,我需要一种方法来浏览层次结构来访问它。值得庆幸的是,Angular提供了一种简单的方法来搜索层次结构。
搜索一个父接口
第一步:创建一个抽象类
我首先创建了一个抽象类,其中包含我希望按钮组件能够访问的属性。
export abstract class View { abstract id: number; abstract index: number;}
第2步:实现抽象类并添加提供者
下一步是实现这个抽象类,并为试图注入它的人提供一个引用。
import { Component, forwardRef, Input } from '@angular/core';import { View } from 'projects/view/src/public-api';
第3步:将接口注入子组件/指令中
最后一步是使用@Optional()装饰器将视图类注入任何需要访问抽象类中定义的父类属性/方法的子类。
export class ViewDeleteComponent {
如果你想看所有三个组件的代码,请查看这个github gist。