MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Blazor - ルーティングのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Blazor - ルーティング
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Blazorでは、URLパターンとコンポーネントを紐付けることでルーティングを実現する。<br> <br> Blazorのルーティングは、<code>@page</code>ディレクティブを使用して設定する。<br> このように定義することにより、/counterというURLにアクセスした時にこのコンポーネントが表示される。<br> <br> <u>※注意</u><br> <u>ファイル名は大文字で始まる必要があり、razorファイルの拡張子は.razorの必要がある。</u><br> <br> <syntaxhighlight lang="c#"> // Pages/Counter.razorファイル @page "/counter" @page "/counter/{currentCount:int}" <h1>Counter</h1> <p>Current count: @currentCount</p> @code { // オプションのルートパラメータ [Parameter] public int currentCount { get; set; } } </syntaxhighlight> <br><br> == ルーティングファイル == Blazorでは、Pagesディレクトリに配置されたrazorファイルがルーティングの対象となる。<br> <br> 以下に示す<u>/counter</u>の場合では、デフォルトでは以下に示すファイルが参照される。<br> * /<プロジェクトのトップディレクトリ>/Pages/Counter.razorファイル <br> <syntaxhighlight lang="c#"> @page "/counter" <h1>Counter</h1> </syntaxhighlight> <br> ただし、これは規約ベースのルーティングであり、<code>@page</code>ディレクティブで明示的に別のルートを指定することも可能である。<br> <br> 以下に示すように設定することにより、異なるファイル配置でも/counterにルーティングすることができる。<br> <syntaxhighlight lang="c#"> // 例 : /Pages/MyCounter/Index.razorファイル @page "/counter" </syntaxhighlight> <br> Pagesディレクトリ配下のファイルへのルーティング<br> * /counter --> /Pages/Counter.razor <br> また、ネストされたディレクトリの場合は以下のようになる。<br> * /mypage --> /Pages/MyPage.razor * /admin/dashboard --> /Pages/Admin/Dashboard.razor * /settings/profile --> /Pages/Settings/Profile.razor <br> 特殊なケースとして、Indexページは以下のようになる。<br> * / --> /Pages/Index.razor * /admin --> /Pages/Admin/Index.razor <br> なお、<code>@page</code>ディレクティブで明示的にルートを指定した場合は、この規約が上書きされる。<br> <br><br> == レンダーフラグメント == レンダーフラグメントは、UIの一部を表すデリゲート型であり、コンポーネント間でコンテンツを受け渡すための仕組みである。<br> これは、JSXのchildren propやReactのprops.childrenに相当する概念である。<br> <br> また、<code>@Body</code>は、このレンダーフラグメントの特別な実装である。<br> <br> <syntaxhighlight lang="c#"> [Parameter] public RenderFragment CustomContent { get; set; } // 使用例 <div> @CustomContent </div> </syntaxhighlight> <br> レンダーフラグメントは、Blazorにおける重要な型であり、以下に示す用途で使用される。<br> <syntaxhighlight lang="c#"> // LayoutComponentBaseクラスでの定義 public RenderFragment Body { get; set; } // カスタムコンポーネントでの使用例 [Parameter] public RenderFragment ChildContent { get; set; } // テンプレート用途での使用例 [Parameter] public RenderFragment<TItem> ItemTemplate { get; set; } </syntaxhighlight> <br> ==== @Body ==== <code>@Body</code>は、レイアウトコンポーネント内でページコンテンツを表示する場所を指定するプレースホルダーである。<br> <br> @Bodyは、レイアウトを使用する各ページのコンテンツが配置される場所を示す。<br> <br> 例えば、以下に示すようなページコンポーネントが存在する場合<br> <syntaxhighlight lang="c#"> // MainLayout.razorファイル <div class="page"> <div class="sidebar"> <NavMenu /> </div> <main> <div class="content"> @Body </div> </main> </div> </syntaxhighlight> <br> <syntaxhighlight lang="c#"> // Pages/Counter.razorファイル @page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() => currentCount++; } </syntaxhighlight> <br> 上記のCounter.razorファイルの内容が、MainLayout.razorファイルの@Body部分に展開されて表示される。<br> <syntaxhighlight lang="c#"> // MainLayout.razorファイル <div class="page"> <div class="sidebar"> <NavMenu /> </div> <main> <div class="content"> // ここに、Counter.razorファイルの内容が展開される <h1>Counter</h1> <p>Current count: 0</p> <button>Click me</button> </div> </main> </div> </syntaxhighlight> <br><br> == パラメータの受け渡し == ルートパラメータは波括弧で囲んで指定して、対応するプロパティに<code>[Parameter]</code>属性を付与する。<br> <br> Blazorのパラメータ受け渡しには、3つの方法がある。<br> <br> ==== ルートパラメータ ==== <syntaxhighlight lang="c#"> @page "/user/{Id:int}" @code { [Parameter] public int Id { get; set; } // 整数以外の値が渡された場合は404エラー } </syntaxhighlight> <br> ==== 複数パラメータ ==== <syntaxhighlight lang="c#"> @page "/orders/{CustomerId:int}/{OrderId:int}" @code { [Parameter] public int CustomerId { get; set; } [Parameter] public int OrderId { get; set; } } </syntaxhighlight> <br> ==== クエリパラメータ ==== <syntaxhighlight lang="c#"> // URL: /search?query=blazor&page=1 @page "/search" @inject NavigationManager Navigation @code { private string SearchQuery; private int Page; protected override void OnInitialized() { var uri = Navigation.ToAbsoluteUri(Navigation.Uri); if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("query", out var query)) { SearchQuery = query; } if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("page", out var page)) { Page = Convert.ToInt32(page); } } } </syntaxhighlight> <br> ==== 制約パターンの使用 ==== 制約パターンも使用できる。<br> <br> <syntaxhighlight lang="c#"> @page "/date/{date:datetime}" @page "/products/{id:guid}" @page "/blog/{*slug}" // catch-allパラメータ </syntaxhighlight> <br> ==== カスケード ==== これらのパラメータは、コンポーネント間でのカスケード時にも使用可能である。<br> <br> <syntaxhighlight lang="c#"> <ChildComponent CustomerId="@CustomerId" /> </syntaxhighlight> <br><br> == ナビゲーション == プログラムによる画面遷移とリンクによる遷移の2つの方法がある。<br> <br> ==== NavigationManagerを使用したプログラムによる遷移 ==== <syntaxhighlight lang="c#"> @inject NavigationManager Navigation @code { private void Navigate() { // 基本的な遷移 Navigation.NavigateTo("counter"); // 強制的なページリロード Navigation.NavigateTo("counter", forceLoad: true); // 相対パスでの遷移 Navigation.NavigateTo("counter", forceLoad: false); // クエリパラメータを含む遷移 Navigation.NavigateTo($"search?query={Uri.EscapeDataString(searchTerm)}"); // 戻る Navigation.NavigateTo(Navigation.Uri); } // URLの変更を検知 protected override void OnInitialized() { Navigation.LocationChanged += LocationChanged; } private void LocationChanged(object sender, LocationChangedEventArgs e) { // URLが変更された時の処理 } } </syntaxhighlight> <br> ==== NavLinkコンポーネントを使用したリンクによる遷移 ==== NavLinkコンポーネントを使用して遷移する。<br> <br> <syntaxhighlight lang="c#"> // 基本的な使用方法 <NavLink href="counter">Counter</NavLink> // アクティブ時のスタイル指定 <NavLink href="counter" ActiveClass="active">Counter</NavLink> // Match属性による一致条件の指定 <NavLink href="users" Match="NavLinkMatch.Prefix">Users</NavLink> </syntaxhighlight> <br><br> == オプションパラメータ / クエリパラメータ == パラメータ処理により、以下に示すようなURLに対応することができる。<br> * /products *: カテゴリなし * /products/1 *: カテゴリID指定 * /products?search=keyboard *: 検索キーワード指定 * /products/1?search=keyboard&page=2 *: 全てのパラメータ指定 <br> ==== オプションパラメータ ==== 波括弧内に<code>?</code>を付加することにより、実現できる。<br> <br> <syntaxhighlight lang="c#"> @page "/user/{id?}" // idパラメータはオプション (省略可能) @page "/blog/{year:int?}/{month:int?}" // 年月も省略可能 @code { [Parameter] public string Id { get; set; } [Parameter] public int? Year { get; set; } [Parameter] public int? Month { get; set; } protected override void OnInitialized() { // パラメータが省略された場合のデフォルト値設定 Id ??= "default"; // Idが未指定の場合は、"default"を設定 Year ??= DateTime.Now.Year; // 年が未指定の場合は現在の年を設定 Month ??= DateTime.Now.Month; // 月が未指定の場合は現在の月を設定 } } </syntaxhighlight> <br> ==== クエリパラメータ ==== <syntaxhighlight lang="c#"> @page "/search" @inject NavigationManager NavigationManager // URLの操作に必要なサービスの注入 @code { // クエリパラメータを格納するディクショナリ private Dictionary<string, string> QueryParameters; protected override void OnInitialized() { // 現在のURLからクエリパラメータを解析 var uri = new Uri(NavigationManager.Uri); QueryParameters = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query) .ToDictionary(p => p.Key, p => p.Value.ToString()); } // 検索条件を更新してページ遷移を行うメソッド private void UpdateSearch(string query, int page) { // クエリパラメータの設定 var parameters = new Dictionary<string, string> { { "q", query }, // 検索キーワード { "page", page.ToString() } // ページ番号 }; // クエリパラメータを含むURLを生成して遷移 var url = QueryHelpers.AddQueryString("/search", parameters); NavigationManager.NavigateTo(url); } } </syntaxhighlight> <br> ==== 2つのパラメータの組み合わせ ==== <syntaxhighlight lang="c#"> @page "/products/{categoryId?}" // カテゴリIDはオプション @inject NavigationManager NavigationManager @code { [Parameter] public string CategoryId { get; set; } // URLパラメータ // クエリパラメータから検索キーワードを取得 private string SearchTerm => GetQueryParameter("search"); // クエリパラメータからページ番号を取得 (デフォルト : 1) private int Page => int.Parse(GetQueryParameter("page") ?? "1"); // クエリパラメータを取得するヘルパーメソッド private string GetQueryParameter(string key) { var uri = new Uri(NavigationManager.Uri); var parameters = QueryHelpers.ParseQuery(uri.Query); return parameters.TryGetValue(key, out var value) ? value.ToString() : null; } } </syntaxhighlight> <br><br> == レイアウトの適用 == Blazorのルーティングでは、レイアウト機能も重要である。<br> レイアウト機能により、共通のUIパーツを効率的に管理でき、ページごとに異なるレイアウトを適用することができる。<br> <br> _Imports.razorファイルにおいて、デフォルトレイアウトを指定して、必要に応じて個別のコンポーネントで<code>@layout</code>指示子を使用して上書きすることができる。<br> <br> ==== 基本的なレイアウトファイルの構造 ==== <syntaxhighlight lang="c#"> // MainLayout.razorファイル @inherits LayoutComponentBase <div class="page"> <div class="sidebar"> <NavMenu /> </div> <main> <div class="content"> @Body </div> </main> </div> </syntaxhighlight> <br> ==== _Imports.razorでのデフォルトレイアウト指定 ==== <syntaxhighlight lang="c#"> @using System.Net.Http @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @layout MainLayout // デフォルトレイアウトの指定 </syntaxhighlight> <br> ==== 個別コンポーネントでのレイアウト上書き ==== <syntaxhighlight lang="c#"> // Pages/AdminPage.razorファイル @layout AdminLayout // このコンポーネントのみ異なるレイアウトを使用 @page "/admin" <h1>管理画面</h1> </syntaxhighlight> <br> ==== 入れ子レイアウトの例 ==== <syntaxhighlight lang="c#"> // AdminLayout.razorファイル @inherits LayoutComponentBase <div class="admin-layout"> <nav class="admin-nav"> <AdminMenu /> </nav> <div class="admin-content"> @Body </div> </div> </syntaxhighlight> <br><br> == エラーハンドリング == 404エラー等のルーティングエラーは、App.razorで設定したNotFoundテンプレートによって処理される。<br> これにより、ユーザフレンドリーなエラー画面を表示することが可能である。<br> <br> 例えば、NotFoundセクションをカスタマイズすることにより、より使用しやすいエラー画面を提供することができる。<br> <br> <syntaxhighlight lang="c#"> // App.razorファイル <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <div class="alert alert-danger"> <h3>ページが見つかりません</h3> <p>申し訳ありません。要求されたページは存在しません。</p> <a href="/" class="btn btn-primary">ホームに戻る</a> </div> </LayoutView> </NotFound> </Router> </syntaxhighlight> <br> ==== カスタム404ページ ==== <syntaxhighlight lang="c#"> // Pages/CustomNotFound.razorファイル @inject NavigationManager NavigationManager <div class="error-container"> <h2>404 - ページが見つかりません</h2> <p>リクエストされたURL: @NavigationManager.Uri</p> <div class="error-actions"> <button @onclick="GoBack">前のページに戻る</button> <a href="/" class="btn">ホームページへ</a> </div> </div> @code { private void GoBack() { NavigationManager.NavigateTo(NavigationManager.Uri); } } </syntaxhighlight> <br> 上記のファイルをApp.razorファイルで使用する。<br> <syntaxhighlight lang="c#"> // App.razorファイル <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <CustomNotFound /> </LayoutView> </NotFound> </syntaxhighlight> <br><br> == 認証 / 認可 == <code>[Authorize]</code>属性を使用することにより、特定のルートへのアクセスを制限することができる。<br> <br> ==== 基本的な認証要求 ==== <syntaxhighlight lang="c#"> @page "/secured-page" [Authorize] public class SecuredPageBase : ComponentBase { // このページは認証済みユーザーのみアクセス可能 } </syntaxhighlight> <br> ==== 特定のロールに基づく認証 ==== <syntaxhighlight lang="c#"> @page "/admin-page" [Authorize(Roles = "Admin")] public class AdminPageBase : ComponentBase { // 管理者ロールを持つユーザーのみアクセス可能 } </syntaxhighlight> <br> ==== 複数のロールの指定 ==== <syntaxhighlight lang="c#"> [Authorize(Roles = "Admin,Manager")] // ポリシーベースの認証 [Authorize(Policy = "RequireAdminRole")] // カスタム認証要件 [Authorize(Policy = "MinimumAgeRequirement")] </syntaxhighlight> <br> ==== Program.csでの認証サービスの設定 ==== <syntaxhighlight lang="c#"> builder.Services.AddAuthentication().AddCookie(); builder.Services.AddAuthorization(options => { options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin")); options.AddPolicy("MinimumAgeRequirement", policy => policy.Requirements.Add(new MinimumAgeRequirement(18))); }); </syntaxhighlight> <br> ==== 認証状態の確認と処理 ==== <syntaxhighlight lang="c#"> @inject AuthenticationStateProvider AuthenticationStateProvider @code { private async Task<bool> IsUserAuthenticated() { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); return authState.User.Identity.IsAuthenticated; } } </syntaxhighlight> <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:C_Sharp]]
Blazor - ルーティング
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse