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 語法也在最新版本的 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區塊
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
自從 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 將不再降級。
因此,應用程式的建置將更快、更輕。
從現在開始,當執行ng dev命令時,應用程式將以開發模式啟動。
實際上,ng dev 指令是ngserve指令的別名。
建立此別名是為了與 Vite 生態系統保持一致,特別是 npm run dev 指令。
Angular 團隊再次交付了一個充滿新功能的版本,無疑將大大增強開發人員的體驗,並向我們展示 Angular 的未來一片光明。
未來我們可以期待什麼?
毫無疑問,性能和開發人員體驗持續改進。
我們還將看到基於訊號的表單、基於訊號的元件的引入,以及很快使用 @let 區塊聲明模板變數的能力。
原文出處:https://dev.to/this-is-angular/whatnew-in-angular-18-60j