Angular のタイプセーフ ルートでランタイム エラーを排除する
Angular アプリケーションのリファクタリングは、諸刃の剣になる可能性があります。一方で、コードベースの保守性とスケーラビリティを向上させることができます。一方、意図しない変更から機能を保護するために必要な予防策を講じていない場合、ルートの破損につながる可能性があります。広範なテストを作成したり、ルートにしっかりとした型付けの概念を実装したりすると、このリスクを軽減できますが、これらのアプローチは時間がかかる可能性があり、常に実行可能であるとは限りません。この記事では、手動でのテスト作業やカスタム型の注釈の記述を必要とせずに、コンパイル時に壊れたルートを自動的に検出する、より効率的なソリューションを検討します。ネストされたコンポーネントを含むサンプル Angular アプリケーションを実装し、typesafe-routes ライブラリを使用して開発者のエクスペリエンスを向上させ、パラメーターの解析を容易にすることで、このアプローチを実証します。
コンパイル時に壊れたルートを自動的に検出する利点を説明するために、DashboardComponent (/dashboard)、OrgsComponent (/orgs/:orgId)、および LocationsComponent (/orgs) の 3 つのネストされたコンポーネントを含むサンプル Angular アプリケーションを実装します。 /: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 をインポートし、最初の引数としてルートを渡します。これらのルートは、ルート レベルでダッシュボードと組織という 2 つのプロパティを持つネストされたオブジェクトとして定義されます。これらの各プロパティにはパスが割り当てられ、配列の形式でセグメントを指定します。たとえば、["dashboard"] 配列はパス /dashboard に対応します。 orgs パスには、整数型の orgId という名前のパラメータが含まれているため、より複雑です。 integer はネイティブ JavaScript 型ではなく、バックグラウンドで数値を使用して整数の特性を模倣する int 関数を使用して定義されたカスタム型であることに注意してください。 orgs ルートには Children プロパティがあり、locations という 1 つの子ルートを指定します。 location ルートは 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 の場合は、対応するパス r.dashboard と r.orgs を指定して template を呼び出すだけで、テンプレートを取得できます。ただし、残りのコンポーネント LocationsComponent は OrgsComponent の子であるため相対パスが必要ですが、Angular Router の場合は絶対パス orgs/:orgId/locations/:locationId になるため、r.orgs.locations を使用して生成することはできません。ルート テンプレートをネストする場合は相対パスが必要です。
相対パスを生成するには、_ リンクを使用できます。これにより、アンダースコア文字より前のすべてが実質的に省略されます。この場合、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 を作成します。最初のパラメータとして、レンダリングされるルートのパスを表す前述のプロキシ オブジェクトを取ります。 2 番目のパラメーターは、app.routes.ts の createRoutes で以前に定義されたパラメーターの名前とタイプに一致するパラメーター値を持つレコードです。戻り値は、対応するコンポーネントに属するパスを含む文字列です。
3 番目の例の render 関数はパスと検索パラメータの両方をレンダリングするため、パラメータ定義にパスとクエリ プロパティが必要です。ここでの戻り値は、パスとクエリの 2 つのプロパティを持つオブジェクトです。 2 つのプロパティを [routerLink] 属性と [queryParams] 属性の値として設定します。
パラメータの解析
パラメータの解析は、typesafe-routes の重要な部分です。上記のルート定義中に、いくつかのパラメーターを定義し、それらに整数のような型 int を与えました。ただし、パラメーター値は Location オブジェクトなどのさまざまなソースから取得されるため、文字列ベースになります。便利なことに、typesafe-routes は、これらの文字列を解析して目的の型にキャストするヘルパー関数をエクスポートします。解析は、前に作成したプロキシ オブジェクト r に基づいて行われます。つまり、パラメータがどのルートに属しているかをライブラリに伝える必要があります。次の例では、2 つの一般的な解析シナリオを示してそれを示します。
// 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 を使用して文字列ベースのクエリ パラメータにアクセスでき、文字列ベースのパス パラメータはこれを通じて提供されます。ルート.スナップショット.パラメータ。 r.orgs.locations および this.route.snapshot.queryParams で parseQuery を使用すると、ページ パラメーターを数値として持つオブジェクトを取得できます。 r.orgs._.locations および this.route.snapshot.params で parsePath を使用すると、解析された 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 に登録するために使用するテンプレートをレンダリングしました。動的パス セグメントとクエリ パラメーターを使用してパスをレンダリングしました。パラメータを解析して文字列値から対応する型に変換しました。私たちは、型定義を 1 つも書かずに、すべてをタイプセーフな方法で実行しました。新しい機能の開発中にバグを簡単に防止し、将来のリファクタリングをさらに容易にする、堅牢なルート ツリーを確立しました。
ただし、typesafe-routes には、さまざまな組み込みパラメータ タイプ、カスタム パラメータ タイプの簡単な統合、サブパスの操作、カスタム テンプレート文字列の定義など、さらに多くの機能があります。残念ながら、このチュートリアルですべてを説明することはできませんが、公式ドキュメントにアクセスして詳細を読むことができます。
プロジェクトを支援する
もちろん、このチュートリアルで示した例に実装できる潜在的な改善点も数多くあります。たとえば、r.orgs.locations などのプロキシ オブジェクトに基づいたパス定義を受け取るリンク レンダリング用のカスタム ディレクティブです。もう 1 つの例は、Angular Router の Routes 配列を自動的に生成する関数です。これにより、重複したコードが効果的に排除され、最初のコード ブロックで createRoutes で作成されたルート ツリーとルートの同期を保つ必要がなくなりました。
ただし、これらは多くの貢献方法の中のほんの一部にすぎません。最も一般的な方法は、もちろん、共有したり、バグを報告したり、GitHub リポジトリで PR を開くことです。このライブラリを使用して、開発エクスペリエンスが向上すると思われる場合は、私にコーヒーをおごっていただいても構いません。フィードバックを残したり、質問したりできる Discord チャンネルもあります。
以上がAngular のタイプセーフ ルートでランタイム エラーを排除するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScriptは、最新のブラウザにすでに組み込まれているため、インストールを必要としません。開始するには、テキストエディターとブラウザのみが必要です。 1)ブラウザ環境では、タグを介してHTMLファイルを埋め込んで実行します。 2)node.js環境では、node.jsをダウンロードしてインストールした後、コマンドラインを介してJavaScriptファイルを実行します。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。
