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’用于变量中的存储条件
- 登录 发表评论