介绍
2024年5月22日星期三,Angular核心团队发布了Angular新版本:版本18。
该版本不仅稳定了最新的API,还引入了许多旨在简化框架的使用并改善开发人员体验的新功能。
这些新功能是什么?请仔细阅读,找出答案。
新的控制流程语法现已稳定
当最新版本的Angular发布时,引入了一种管理视图流的新方法。提醒一下,这个新的控制流程直接整合到Angular模板编译器中,使以下结构指令成为可选:
- 动图
- 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函数所致。
正如我上面提到的,由于Angular 18版本一直基于这个新的调度程序,因此当您迁移应用程序时,不会出现任何问题,因为Angular可能会收到Zone Js和/或这个新调度程序的检测更改通知。
但是,要回到Angular 18之前的行为,您可以使用provideZoneChangeDetection函数,并将ignoreChangesOutsideZone setter选项设为true。
bootstrapApplication(AppComponent,{
providers: [
provideZoneChangeDetection({ ignoreChangesOutsideZone: true })
]
});
另外,如果您希望仅依赖新的排程器而不依赖Zone Js,则可以使用ProvideExperimentalZonelessChangeDetection函数。
bootstrapApplication(AppComponent,{
providers: [
provideExperimentalZonelessChangeDetection()
]
});
透过实现provideExperimentalZonelessChangeDetection函数,Angular不再依赖Zone Js,这使得
- 如果项目的其他依赖项均不依赖它,则删除Zone js依赖项
- 从angular.json档案中的polifills中删除区域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是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继承该属性),该属性传回一个observable
@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格式传送回浏览器,显示一个静态页面,然后由于水化现象而变得动态。在此水合阶段期间,无法传送对互动的响应,因此使用者互动会遗失,直到水合完成为止。
Angular能够记录此水合作用阶段的用户交互,并在应用程序完全加载并交互后回放它们。
若要解锁此功能,仍处于开发者预览版,您可以使用ServerSideFeature withReplayEvents函数。
providers: [
provideClientHydration(withReplayEvents())
]
国际化
随着Angular 16的发布,Angular改变了页面水合的方式。破坏性水合作用已被渐进性水合作用所取代。然而,当时缺乏一个重要的功能:国际化支持。Angular跳过了标记为i18n的元素。
有了这个新版本,这种情况就不再是这样了。请注意,此功能仍处于开发预览阶段,可以使用withI18nSupport函数启动。
providers: [
provideClientHydration(withI18nSupport())
]
国际化
Angular建议使用INTL原生javascript API来处理与Angular应用程序国际化相关的所有事务。
根据此建议, @angular/common套件公开的函数助手已被弃用。因此,不再建议使用getLocaleDateFormat等函数。
新的建构器包和弃用
到目前为止,自从Angular中出现vite以来,用于建立Angular应用程序的建构器位于以下套件中: @angular-devkit/build-angular
该套件包含Vite、Webpack和Esbuild。对于将来仅使用Vite和Esbuild的应用程序来说,这个套件太重了。
考虑到这一潜在的未来,一个仅包含Vite和Esbuild的新包被建立,名称为@angular/build
迁移到Angular 18时,如果应用程序不依赖webpack(例如,没有基于Karma的单元测试),则可以执行可选原理图。此原理图将修改angular.json档案以使用新套件,并透过新增套件和删除旧套件来更新package.json。
重要的是,旧包可以继续使用,因为它为新包提供了别名。
透过在项目的node_modules中加入必要的依赖项,Angular开箱即用地支持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,即使目前仍处于实验阶段,如果不再在polyfill中声明ZoneJs,Angular将不再降级。
因此,应用程序的建置将更快、更轻。
新别名:by dev
从现在开始,当执行ng dev命令时,应用程序将以开发模式启动。
实际上,ng dev指令是ngserve指令的别名。
建立此别名是为了与Vite生态系统保持一致,特别是npm run dev指令。
未来
Angular团队再次交付了一个充满新功能的版本,无疑将大大增强开发人员的体验,并向我们展示Angular的未来一片光明。
未来我们可以期待什么?
毫无疑问,性能和开发人员体验持续改进。
我们还将看到基于信号的表单、基于信号的元件的引入,以及很快使用@let内存块声明模板变数的能力。
原文出处:https://dev.to/this-is-angular/whatnew-in-angular-18-60j
最新评论