Angular 18 中的新功能
介绍
2024 年 5 月 22 日星期三,Angular 核心团队发布 Angular 的新版本:版本 18。
此版本不仅稳定了最新的 API,还引入了许多旨在简化框架使用和改善开发人员体验的新功能。
这些新功能是什么?继续阅读,一探究竟。
新的控制流语法现已稳定
Angular 最新版本发布时,引入了一种管理视图流的新方法。需要提醒的是,这种新的控制流直接集成到了 Angular 模板编译器中,使得以下结构型指令成为可选的:
- ngIf
- ngFor
- ngSwitch / ngSwitchCase
<!-- old way -->
<div *ngIf="user">{{ user.name }}</div>
<!-- new way -->
@if(user) {
<div>{{ user.name }}</div>
}
这个新的 API 现在已经稳定,我们建议使用这个新语法。
如果您想将您的应用程序迁移到这个新的控制流,可以使用示意图。
ng g @angular/core:control-flow
此外,新的@for语法取代了 ngFor 指令,迫使我们使用 track 选项来优化列表的渲染并避免在更改期间完全重新创建它们。
开发模式中增加了两个新的警告:
-
如果跟踪键重复,则会发出警告。如果所选键值在您的集合中不唯一,则会发出此警告。
-
如果跟踪键是整个项目,并且选择此键会导致整个列表被销毁并重新创建,则会发出警告。如果操作成本过高(但门槛较低),则会显示此警告。
Defer 语法现在稳定了
@defer语法也是在 Angular 的最新版本中引入的,它允许你定义一个块,当满足某个条件时,该块会被延迟加载。当然,此块中使用的任何第三方指令、管道或库也将被延迟加载。
以下是其使用示例
@defer(when user.name === 'Angular') {
<app-angular-details />
}@placeholder {
<div>displayed until user.name is not equal to Angular</div>
}@loading(after: 100ms; minimum 1s) {
<app-loader />
}@error {
<app-error />
}
提醒一下,
- 只要不满足@defer块条件,就会显示@placeholder块
- 当浏览器下载@defer块的内容时,将显示@loading块;在我们的例子中,如果下载时间超过100毫秒,将显示块加载,并且至少显示1秒。
- 如果下载@defer块时发生错误,则会显示@error块
Zone.js 将会怎样
Angular 18 引入了一种触发检测变更的新方法。之前,检测变更完全由 Zone.js 处理,这并不令人意外。现在,检测变更将由框架本身直接触发。
为了实现这一点,框架中新增了一个新的变更检测调度器 ( ChangeDetectionScheduler ),该调度器将在内部用于触发变更检测。这个新的调度器不再基于 Zone.js,而是在 Angular 18 版本中默认使用。
如果发生以下情况,新的调度程序将引发检测变化
- 触发模板或主机监听事件
- 视图被附加或删除
- 异步管道接收新值
- markForCheck 函数被调用
- 信号值发生变化等。
小文化时刻:这种检测变化是由于内部调用了ApplicationRef.tick函数。
正如我上面提到的,由于 18 版 Angular 已经基于这个新的调度程序,因此当您迁移应用程序时,不会发生任何中断,因为 Angular 可能会收到 Zone Js 和/或这个新调度程序的检测更改通知。
但是,要恢复到 Angular 18 之前的行为,您可以使用 provideZoneChangeDetection 函数并将ignoreChangesOutsideZone setter 选项设置为 true。
bootstrapApplication(AppComponent, {
providers: [
provideZoneChangeDetection({ ignoreChangesOutsideZone: true })
]
});
此外,如果您希望仅依赖新的调度程序而不依赖 Zone Js,则可以使用provideExperimentalZonelessChangeDetection函数。
bootstrapApplication(AppComponent, {
providers: [
provideExperimentalZonelessChangeDetection()
]
});
通过实现provideExperimentalZonelessChangeDetection函数,Angular 不再依赖于 ZoneJs,这使得
- 如果项目的其他依赖项都不依赖 Zone js,则删除 Zone js 依赖项
- 从 angular.json 文件中的 polifills 中删除 zone js
HttpClientModule 的弃用
自从 Angular 14 版和独立组件的出现以来,模块在 Angular 中已成为可选项,现在是时候看到第一个被弃用的模块了:我将 HttpClientModule 命名为
该模块负责为整个应用程序注册 HttpClient 单例,以及注册拦截器。
该模块可以轻松地由provideHttpClient函数替换,并具有支持 XSRF 和 JSONP 的选项。
此函数有一个用于测试的孪生姐妹:provideHttpClientTesting
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient()
]
});
与往常一样,Angular 团队提供了示意图来帮助您迁移应用程序。
当发出ng update @angular/core @angular /cli命令时,如果在应用程序中使用 HttpClientModule,则会发出迁移请求
ng-content 回退
ng-content 是 Angular 中的一个重要特性,尤其是在设计通用组件时。
此标签允许您投射您自己的内容。但是,此功能有一个主要缺陷。您无法为其指定默认内容。
从版本 18 开始,情况不再如此。您可以将内容放在如果开发人员未提供任何内容,则会显示该标签。
我们以按钮组件为例
<button>
<ng-content select=".icon">
<i aria-hidden="true" class="material-icons">send</i>
</ng-content>
<ng-content></ng-content>
</button>
使用按钮组件时,如果没有提供带有图标类的元素,则会显示图标发送
表单事件:对表单事件进行分组的方式
这是社区很久以前提出的一个请求:有一个 API 可以将表单中可能发生的事件分组;当我说事件时,我指的是以下事件
- 原始的
- 感动
- 状态改变
- 重置
- 提交
Angular 18 版本从 AbstractControl 类中公开了一个新的事件属性(允许 FormControl、FormGroup 和 FormArray 继承此属性),该属性返回一个可观察的
@Component()
export class AppComponent {
login = new FormControl<string | null>(null);
constructor() {
this.login.events.subscribe(event => {
if (event instanceof TouchedChangeEvent) {
console.log(event.touched);
} else if (event instanceof PristineChangeEvent) {
console.log(event.pristine);
} else if (event instanceof StatusChangeEvent) {
console.log(event.status);
} else if (event instanceof ValueChangeEvent) {
console.log(event.value);
} else if (event instanceof FormResetEvent) {
console.log('Reset');
} else if (event instanceof FormSubmitEvent) {
console.log('Submit');
}
})
}
}
路由:重定向作为函数
在 Angular 的最新版本之前,当你想要重定向到另一个路径时,你需要使用redirectTo属性。该属性的值只能是一个字符串
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMath: 'full' },
{ path: 'home', component: HomeComponent }
];
现在可以使用此属性传递一个函数。该函数接受ActivatedRouteSnapshot作为参数,允许您从 URL 中检索 queryParams 或 params。
另一个有趣的点是,此函数在注入上下文中调用,从而可以注入服务。
const routes: Routes = [
{ path: '', redirectTo: (data: ActivatedRouteSnapshot) => {
const queryParams = data.queryParams
if(querParams.get('mode') === 'legacy') {
const urlTree = router.parseUrl('/home-legacy');
urlTree.queryParams = queryParams;
return urlTree;
}
return '/home';
}, pathMath: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'home-legacy', component: HomeLegacyComponent }
];
服务器端渲染:两个很棒的新功能
Angular 18 引入了两个重要且备受期待的新服务器端渲染功能
- 事件重播
- 国际化
重播事件
当我们创建一个服务器端渲染应用程序时,该应用程序会以 HTML 格式发送回浏览器,显示一个静态页面,然后由于 hydration 现象,该页面会变为动态页面。在此 hydration 阶段,无法发送任何交互响应,因此用户交互会丢失,直到 hydration 完成。
Angular 能够记录此水化阶段的用户交互,并在应用程序完全加载并可交互后重播它们。
要解锁此功能,仍在开发人员预览中,您可以使用 ServerSideFeature withReplayEvents函数。
providers: [
provideClientHydration(withReplayEvents())
]
国际化
随着 Angular 16 的发布,Angular 改变了页面数据同步的方式。破坏性数据同步已被渐进式数据同步所取代。然而,当时缺少一项重要功能:国际化支持。Angular 跳过了标记为 i18n 的元素。
新版本中不再存在这种情况。请注意,此功能仍处于开发预览阶段,可以使用withI18nSupport函数激活。
providers: [
provideClientHydration(withI18nSupport())
]
国际化
Angular 建议对于与 Angular 应用程序国际化有关的所有事宜使用 INTL 原生 javascript API。
根据此建议, @angular/common包暴露的函数助手已被弃用。因此,例如 getLocaleDateFormat 之类的函数不再被推荐使用。
新的构建器包和弃用
到目前为止,自从 vite 出现在 Angular 中以来,用于构建 Angular 应用程序的构建器都在包中:@angular-devkit/build-angular
这个软件包包含 Vite、Webpack 和 Esbuild。对于未来只使用 Vite 和 Esbuild 的应用程序来说,这个软件包太重了。
考虑到这个潜在的未来,我们创建了一个仅包含 Vite 和 Esbuild 的新包,名称为@angular/build
迁移到 Angular 18 时,如果应用程序不依赖 Webpack(例如,没有基于 Karma 的单元测试),则可以运行一个可选的原理图。该原理图将修改 angular.json 文件以使用新的包,并通过添加新包并删除旧包来更新 package.json。
重要的是,旧包可以继续使用,因为它为新包提供了别名。
Angular 通过在项目的 node_modules 中添加必要的依赖项,开箱即用地支持 Less Sass Css 和 PostCss。
然而,随着新的@angular/build包的到来,Less 和 PostCss 变得可选,并且必须在 package.json 中明确作为开发依赖项。
当您迁移到 Angular 18 时,如果您希望使用新包,这些依赖项将自动添加。
不再需要向下层异步/等待
Zone.js 不支持 JavaScript 的async/await特性。
为了不限制开发者使用此功能,Angular 的 CLI 会将使用async/await 的代码转换为“常规”的 Promise。
这种转换称为降级,就像将 Es2017 代码转换为 Es2015 代码一样。
随着不再基于 Zone.js 的应用程序的出现,即使目前仍处于实验阶段,如果 Zone.js 不再在 polyfill 中声明,Angular 也不会降级。
因此,应用程序的构建将更快、更轻量。
新的别名:ng dev
从现在开始,当运行ng dev命令时,应用程序将以开发模式启动。
实际上,ng dev 命令是ng serve命令的别名。
创建此别名是为了与 Vite 生态系统保持一致,特别是 npm run dev 命令。
未来
Angular 团队再次发布了一个充满新功能的版本,这无疑将极大地增强开发人员的体验,并向我们展示 Angular 的未来一片光明。
我们对未来有何期待?
毫无疑问,性能和开发人员体验将继续得到改善。
我们还将看到基于信号的形式、基于信号的组件的引入,以及很快使用@let 块声明模板变量的能力。
文章来源:https://dev.to/this-is-angular/whatnew-in-angular-18-60j