Angular不断发展,创建组件的方法也在不断发展。加入我的组件开发指南之旅
去Angular 17是一段漫长的旅程。在保持向后兼容性的同时,Angular团队正在不断发展框架。和许多其他人一样,我发现自己一直在思考使用什么以及何时使用它。在本文中,我将表达我对创建新组件时应该使用什么的想法。
Signals
信号从版本16开始就可用了,它们是应用程序上管理状态的必备工具。如果你还没有使用Signals,是时候开始使用了。最初,可能会有一个学习曲线,但它很简单,随着时间的推移,它会变得很自然。与OnPush变化检测相结合,它提供了精细调整的反应性、性能增益和令人愉快的开发体验。
Observables
如果我们有信号,为什么我们需要可观察性?请记住,信号处理同步反应性,而可观察性处理异步反应性,例如HTTP请求,同时为我们提供与这些值交互的工具(map、switchMap)。
ChangeDetection.OnPush
首先,对每一个进行简要说明:
默认值:Angular触发对浏览器事件、计时器、XHR和承诺的更改检测。然后,系统从上到下依次检查组件树中的每个组件。在大型系统中,这可能会导致性能问题。
OnPush:它禁用默认的更改检测。简而言之,该组件仅在少数特定情况下重新渲染:
- 异步管道新值
- 输入引用已更改(引用,而不是值,不变性)。
- 源自组件或其中一个子级的事件。
- 手动触发器
那么,仅仅通过阅读以上内容,你就已经知道了吗?正确的
始终使用ChangeDetection。OnPush,当与Signals结合时,您可以将组件性能提升到另一个级别。此外,当Angular完成完全无区域的实现时,您的应用程序离实现它又近了一步。
控制流程
@if (a > b) { {{a}} is greater than {{b}} }
自V17以来,我们为Angular提供了新的控制流程。是的,它在开发者预览版中,但它感觉非常自然和强大,因为它和js语法完全一样。因此,你应该使用它。然而,我发现自己仍然经常使用旧的*ngIf指令。有时你只想隐藏一个<span>,我认为这仍然比写三行更容易。可用的块是@If、@for、@switch。
Inject() VS constructor()
这个决定可能具有挑战性。我目前使用inject(),了解这两种方法的优缺点,尽管详细的探索超出了本文的讨论范围。
在我的特定情况下,对inject()的偏好很大程度上是由于语法糖。它与其他框架中的约定更加无缝地一致。尽管遇到了一些开发人员(最初包括我自己)的抵制,但在代码可读性方面,这种转变还是有回报的。然而,需要注意的是,我们并没有完全从使用constructor()中解放出来。我非常依赖它,尤其是Signal effect(),因为它们需要在注入上下文中运行。我发现这是在这种情况下最直接的方法。
供参考的组件:
import { ChangeDetectionStrategy, Component, inject, signal, } from '@angular/core'; import { MsalService } from '@azure/msal-angular'; import { UsersService } from 'src/app/api/users-services'; import { Observable } from 'rxjs'; import { AsyncPipe, DatePipe } from '@angular/common'; export interface UserDetail { id: string; key: string; timestamp: string; } @Component({ selector: 'app-users-widget', template: `<div> @if ((detailsList$ | async); as userData){ <div> @for(data of userData; track data.id){ <div (click)="setDetails(data)"> {{ data.id }} </div> } </div> } @if (openDetail(); as openDetail){ <h2>User Details</h2> <p>{{ openDetail.id }}</p> <p>{{ openDetail.key }}</p> <p>{{ openDetail.timestamp | date : 'long' }}</p> } </div> `, standalone: true, imports: [DatePipe, AsyncPipe], changeDetection: ChangeDetectionStrategy.OnPush, }) export class UsersWidgetComponent { usersService = inject(UsersService); //# for private modifier #authService = inject(MsalService); openDetail = signal<UserDetail | null>(null); detailsList$: Observable<Array<UserDetail>> = new Observable(); //Using the constructor instead of the ng lifecycle constructor() { this.retrieveFlowHistoryData(); } retrieveFlowHistoryData() { const { username } = this.#authService.instance.getAllAccounts()[0]; this.detailsList$ = this.usersService.apiFlowsHistoryGet$Json({ UserName: username, }); } setDetails(detail: UserDetail) { this.openDetail.set(detail); } }
包装
浏览不断发展的库和框架可能是一项具有挑战性的任务。我相信这篇文章已经为您提供了一些最新的Angular约定的见解。直到下一次!
TL;DR
✅ 独立
✅ 注射
✅ 控制流程
✅ 可观察的
✅ 变更检测。OnPush
✅ Typescript private#修饰符
✅✅ 信号
✅ ‘as’用于变量中的存储条件
- 登录 发表评论