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

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 id="Absolute-Links">Absolute Links</h1>
    
`, }) 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
Python和JavaScript:了解每個的優勢Python和JavaScript:了解每個的優勢May 06, 2025 am 12:15 AM

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

See all articles

熱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

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

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SublimeText3 Mac版

SublimeText3 Mac版

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