首頁 web前端 js教程 使用 Angular 中的類型安全路由消除執行階段錯誤

使用 Angular 中的類型安全路由消除執行階段錯誤

Jan 06, 2025 am 07:22 AM

Eliminate Runtime Errors with Type-safe Routes in Angular

重建 Angular 應用程式可能是一把雙面刃。一方面,它允許您提高程式碼庫的可維護性和可擴展性。另一方面,如果您沒有採取必要的預防措施來保護您的功能免受意外更改,則可能會導致路由中斷。編寫廣泛的測試或為路由實現可靠的類型概念可以幫助減輕這種風險,但這些方法可能非常耗時,而且可能並不總是可行。在本文中,我們將探索一種更有效的解決方案,該解決方案可以在編譯時自動檢測損壞的路由,而無需手動測試工作或編寫自訂類型註解。我們將透過實作具有巢狀元件的範例 Angular 應用程式並使用 typesafe-routes 函式庫來示範此方法,以改善開發人員體驗並促進參數解析。

為了說明在編譯時自動偵測損壞的路由的好處,我們將實作一個具有三個巢狀元件的範例Angular 應用程式:DashboardComponent (/dashboard)、OrgsComponent (/orgs/:orgId) 和LocationsComponent (/ orgs) /:orgId/locations/:locationId)。要設定此範例,我們需要安裝 typesafe-routes 函式庫並使用其 createRoutes 函數來定義我們的路由樹,如下列程式碼片段所示。

// app.routes.ts
import { createRoutes, int } from "typesafe-routes";

export const r = createRoutes({
  dashboard: {
    path: ["dashboard"], // ~> "/dashboard"
  },
  orgs: {
    path: ["orgs", int("orgId")], // ~> "/orgs/:orgId"
    children: {
      locations: {
        path: ["locations", int("locationId")], // ~> "locations/:locationId"
        query: [int.optional("page")], // ~> "?page=[number]"
      },
    },
  },
});
登入後複製
登入後複製
登入後複製

讓我們仔細看看程式碼片段。我們從 typesafe-routes 匯入 createRoutes 並將我們的路由作為其第一個參數傳遞。這些路由被定義為一個嵌套對象,在根層級具有兩個屬性:儀表板和組織。每個屬性都指派一個路徑,以陣列的形式指定段。例如,[“dashboard”]陣列對應於路徑/dashboard。 orgs 路徑更複雜,因為它包含一個名為 orgId 的整數類型參數。請注意,整數不是原生 JavaScript 類型,而是使用 int 函數定義的自訂類型,它在背景使用數字來模仿整數的特徵。 orgs 路由有一個children 屬性,它指定一個名為locations 的子路由。 Locations 路由與 orgs 路由類似,但它指定了一個額外的可選 int 類型的搜尋參數頁面。

createRoutes 使用有關路由的資訊來建立包裝在 Proxy 物件中的上下文。您不需要了解有關該代理對象的詳細信息,但必須了解,由於該對象,您可以訪問應用程式中任何位置的所有路由規範來渲染和解析路由和參數。

我們將createRoutes傳回的Proxy物件指派給r。這意味著您可以使用 r.dashboard 存取儀表板路徑,使用 r.orgs.locations 存取位置路徑,等等。

渲染模板

定義了路由後,我們現在可以繼續下一步:使用 Angular-router 註冊它們。

// app.routes.ts
import { createRoutes, int } from "typesafe-routes";

export const r = createRoutes({
  dashboard: {
    path: ["dashboard"], // ~> "/dashboard"
  },
  orgs: {
    path: ["orgs", int("orgId")], // ~> "/orgs/:orgId"
    children: {
      locations: {
        path: ["locations", int("locationId")], // ~> "locations/:locationId"
        query: [int.optional("page")], // ~> "?page=[number]"
      },
    },
  },
});
登入後複製
登入後複製
登入後複製

程式碼片段顯示了 Angular Router 的巢狀路由的常見設置,它反映了我們先前定義的路由樹。但是,我們沒有使用典型的純字串來指定路徑模板(例如 orgs/:orgId),而是從 typesafe-routes/angular-router 匯入模板函數並使用它來產生路徑模板。對於DashboardComponent和OrgsComponent,我們可以簡單地呼叫template及其對應的路徑r.dashboard和r.orgs來取得模板。然而,剩下的元件LocationsComponent 是OrgsComponent 的子元件,因此需要一個相對路徑,該路徑不能透過使用r.orgs.locations 生成,因為這會導致絕對路徑orgs/:orgId/locations/:locationId,而Angular Router嵌套路由模板時需要相對路徑。

要產生相對路徑,我們可以使用 _ 鏈接,它有效地忽略下劃線字元之前的所有內容。在這種情況下,我們可以使用 template(r.orgs._.locations) 來產生相對路徑。這是一個方便的功能,因為它允許我們在需要渲染絕對路徑的場景以及需要相對路徑的情況下重複使用相同的路由樹。

此時,我們已經在我們最喜歡的 IDE(例如 Visual Studio Code)中利用了自動完成和拼字錯誤預防功能。未來的變更將提醒我們路由路徑中的任何拼字錯誤或拼字錯誤,因為所有類型都可以使用 createRoutes 追溯到初始路由定義。

渲染連結

現在我們已經指定了路線模板,我們要繼續進行連結渲染。為此,我們希望創建一個簡單的元件,利用渲染函數來渲染這些鏈接,包括類型序列化和類型檢查。下一個範例顯示了一個元件,該元件呈現引用我們應用程式中其他元件的錨元素清單。

// app.routes.ts
import { Routes } from "@angular/router";
import { template } from "typesafe-routes/angular-router";

export const routes: Routes = [
  {
    path: template(r.dashboard), // ~> "dashboard"
    component: DashboardComponent,
  },
  {
    path: template(r.orgs), // ~> "orgs/:orgId"
    component: OrgsComponent,
    children: [
      {
        path: template(r.orgs._.locations), // ~> "locations/:locationId"
        component: LocationsComponent,
      },
    ],
  },
];
登入後複製
登入後複製

程式碼範例從 typesafe-routes/angular-router 匯入 render 和 renderPath。 renderPath 渲染路徑,而 render 也序列化連結清單的查詢參數。我們還導入 r,代理對象,它允許我們訪問有關先前定義的路線的資訊並定義要渲染的所需路線。

首先,我們使用 renderPath 函數建立dashboardLink 和orgsLink。作為第一個參數,它採用前面提到的代表要渲染的路線的路徑的代理物件。第二個參數是一筆記錄,其參數值與先前在 app.routes.ts 中使用 createRoutes 定義的參數的名稱和類型相符。傳回值是一個字串,包含屬於對應元件的路徑。

第三個範例中的渲染函數渲染路徑和搜尋參數,因此在參數定義中需要路徑和查詢屬性。這裡的回傳值是一個對象,有path和query兩個屬性。我們將這兩個屬性設定為 [routerLink] 和 [queryParams] 屬性的值。

解析參數

參數解析是型別安全路由的重要組成部分。在上面的路由定義過程中,我們定義了幾個參數並給它們一個類似整數的類型 int。但是,由於參數值來自各種來源(例如 Location 物件),因此它們是基於字串的。方便的是,typesafe-routes 導出解析這些字串並將其轉換為所需類型的輔助函數。解析是基於我們先前建立的代理物件 r,這意味著我們必須告訴函式庫參數屬於哪個路由。下一個範例透過顯示兩個常見的解析場景來示範這一點。

// app.routes.ts
import { createRoutes, int } from "typesafe-routes";

export const r = createRoutes({
  dashboard: {
    path: ["dashboard"], // ~> "/dashboard"
  },
  orgs: {
    path: ["orgs", int("orgId")], // ~> "/orgs/:orgId"
    children: {
      locations: {
        path: ["locations", int("locationId")], // ~> "locations/:locationId"
        query: [int.optional("page")], // ~> "?page=[number]"
      },
    },
  },
});
登入後複製
登入後複製
登入後複製

給定location.href orgs/1/location/2?page=5,在Angular 中,我們可以使用this.route.snapshot.queryParams 存取基於字串的查詢參數,並且透過此提供基於字串的路徑參數。路線.快照.參數。將 parseQuery 與 r.orgs.locations 和 this.route.snapshot.queryParams 結合使用,我們可以檢索頁面參數為數字的物件。將 parsePath 與 r.orgs._.locations 和 this.route.snapshot.params 一起使用,我們得到解析後的 locationId。在這種情況下,r.orgs._.locations 是相對路徑,並且 _ 連結之前的所有段落都被省略,導致 orgId 不存在於結果物件中。

typesafe-routes 中的解析函數是通用的,我們也可以使用 parse 直接從 location.href 字串中一次提取所有參數。

// app.routes.ts
import { Routes } from "@angular/router";
import { template } from "typesafe-routes/angular-router";

export const routes: Routes = [
  {
    path: template(r.dashboard), // ~> "dashboard"
    component: DashboardComponent,
  },
  {
    path: template(r.orgs), // ~> "orgs/:orgId"
    component: OrgsComponent,
    children: [
      {
        path: template(r.orgs._.locations), // ~> "locations/:locationId"
        component: LocationsComponent,
      },
    ],
  },
];
登入後複製
登入後複製

可以透過 InferQueryParams、InferPathParams 或 InferParams 提取有關參數的類型資訊。這是 InferQueryParams 實用程式類型的示範。

// app.component.ts
import { render, renderPath } from "typesafe-routes/angular-router";
import { r } from "./app.routes";

@Component({
  selector: "app-root",
  imports: [RouterOutlet, RouterLink],
  template: `
    <h1>Absolute Links</h1>
    <ul>
      <li><a [routerLink]="dashboardLink">Dashboard</a></li>
      <li><a [routerLink]="orgsLink">Org</a></li>
      <li>
        <a [routerLink]="locationLink.path" [queryParams]="locationLink.query">
          Location
        </a>
      </li>
    </ul>
    <router-outlet></router-outlet>
  `,
})
export class AppComponent {
  dashboardLink = renderPath(r.dashboard, {}); // ~> dashboard
  orgsLink = renderPath(r.orgs, { orgId: 123 }); // ~> orgs/123

  locationLink = render(r.orgs.locations, {
    path: { orgId: 321, locationId: 654 },
    query: { page: 42 },
  }); // ~> { path: "orgs/321/location/654", query: { page: "42" }}
}
// ...
登入後複製

總結

為了結束本教程,我們創建了一個路由樹 r,它是我們路由的唯一事實來源。基於此,我們渲染了用於向 Angular Router 註冊元件的模板。我們使用動態路徑段和查詢參數渲染路徑。我們解析參數,將它們從字串值轉換為對應的類型。我們以類型安全的方式完成了所有事情,甚至沒有編寫一個類型定義。我們建立了一個強大的路由樹,可以在開發新功能時輕鬆防止錯誤,並進一步促進未來的重構。

但是,typesafe-routes 還有更多功能,例如許多不同的內建參數類型、自訂參數類型的輕鬆整合、子路徑的操作、定義自訂模板字串等等。不幸的是,我們無法在本教程中涵蓋所有內容,但您可以透過造訪官方文件來了解更多資訊。

支援專案

當然,也可以對本教程中所示的範例實施許多潛在的改進。例如,用於連結呈現的自訂指令,它採用基於代理物件的路徑定義,例如 r.orgs.locations。另一個例子是一個為 Angular Router 自動產生 Routes 陣列的函數,有效地消除了重複的程式碼,並且無需使路由與第一個程式碼區塊中使用 createRoutes 建立的路由樹保持同步。

但是,這些只是眾多貢獻方式中的幾種。當然,最常見的方式是在我們的 GitHub 儲存庫中共用、報告錯誤或開啟 PR。如果你使用這個庫並認為它改善了你的開發體驗,你也可以請我喝杯咖啡。我們還有一個 Discord 頻道,您可以在其中留下回饋或提出問題。

以上是使用 Angular 中的類型安全路由消除執行階段錯誤的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1662
14
CakePHP 教程
1418
52
Laravel 教程
1311
25
PHP教程
1261
29
C# 教程
1234
24
神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles