はじめに
ふと興味本位でBlazorを触ってみようと思い、以下の公式のラーニングパスをやってみてます。
learn.microsoft.com
そのときに学んだことをメモがてらに残しておきたいと思います。正直自分宛のメモなので、気になる方は公式のものをみてください。
ダウンロード&インストール
.NET 8 SDK
がインストールされていることを確認してください。
$ dotnet --version 8.0.100
されていない場合はインストールします。
https://download.visualstudio.microsoft.com/download/pr/3b11b408-68e1-4a8f-a0ad-55b21456c4f6/03819d38c79a9aa4fd806f8c7b64130d/dotnet-sdk-8.0.101-osx-x64.pkg
アプリの作成
アプリの作成はdotnet new blazor
コマンドを利用します。
$ dotnet new blazor -o MyFirstBlazorApp テンプレート "Blazor Web アプリ" が正常に作成されました。 このテンプレートには、Microsoft 以外のパーティのテクノロジーが含まれています。詳しくは、https://aka.ms/aspnetcore/8.0-third-party-notices をご覧ください。 作成後の操作を処理しています... /Users/user/Blazor/MyFirstBlazorApp/MyFirstBlazorApp.csproj を復元しています: 復元対象のプロジェクトを決定しています... /Users/user/Blazor/MyFirstBlazorApp/MyFirstBlazorApp.csproj を復元しました (182 ms)。 正常に復元されました。
Program.cs
は、サーバーを起動するアプリのエントリ ポイントであり、アプリ サービスとミドルウェアを構成する場所です。App.razor
は、アプリ向けルート コンポーネントです。Routes.razor
は、Blazor ルーターを構成します。Components/Pages
ディレクトリには、アプリ向けのサンプル Web ページが含まれています。BlazorApp.csproj
では、アプリ プロジェクトとその依存関係を定義しています。Properties
内のlaunchSettings.json
は、ローカル開発環境のさまざまなプロファイル設定を定義します。ポート番号は、プロジェクトの作成時に自動的に割り当てられ、このファイルに保存されます。
アプリを実行する
アプリを実行するにはdotnet watch
を利用します。
$ dotnet watch dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload. 💡 Press "Ctrl + R" to restart. dotnet watch 🔧 Building... 復元対象のプロジェクトを決定しています... 復元対象のすべてのプロジェクトは最新です。 MyFirstBlazorApp -> /Users/user/Blazor/MyFirstBlazorApp/bin/Debug/net8.0/MyFirstBlazorApp.dll dotnet watch 🚀 Started warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35] No XML encryptor configured. Key {----} may be persisted to storage in unencrypted form. info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5226 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /Users/user/Blazor/MyFirstBlazorApp warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3] Failed to determine the https port for redirect.
http://localhost:<port number>
を開くとBlazorアプリが実行されているはずです。
カウンターの実装について
サンプルコード上でのカウンター実装について見てみます。該当ファイルはComponents/Pages/Counter.razor
です。
@page "/counter" @rendermode InteractiveServer <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p role="status">Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
@page "/counter"
よりブラウザでhttp://localhost:5226/counter
のように指定するとCounterコンポーネントの内容がレンダリングされ、@rendermode InteractiveServer
を用いることでブラウザからユーザーインターフェイスイベントを処理できるようになります。
button
がクリックされるとonclick
イベントが発生し、IncrementCount
メソッドが実行、currentCount
が増分してコンポーネントがレンダリングされます。
@code
やpage
, @rendermode
といったRazorディレクティブの詳細を知りたい方は公式ドキュメントをご覧ください。
コンポーネント
.razor
ファイルは再利用可能なUIコンポーネントが定義されています。
コンポーネントパラメーターを定義することで、属性または子コンテンツを使用して指定され、それは子コンポーネントのプロパティを設定できます。
@page "/counter" @rendermode InteractiveServer <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p role="status">Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; // Parameter属性を渡すことでコンポーネントパラメーターとして扱えるようになる [Parameter] public int IncrementAmount { get; set; } = 1; private void IncrementCount() { currentCount += IncrementAmount; } }
<!-- コンポーネントパラメーターを渡す --> <Counter IncrementAmount="10" />
データバインディングとイベント
C#色の値をレンダリングする場合は先頭に@
を使用します。
<p role="status">Current count: @currentCount</p>
<!-- @の開始と終了を明示的に指定した場合 --> <p role="status">Current count: @(currentCount)</p>
制御フローを追加する
<!-- 条件付きでレンダリング --> @if (currentCount > 3) { <p>You win!</p> }
<!-- コレクションの一覧をレンダリング --> <ul> @foreach (var item in items) { <li>@item.Name</li> } </ul>
@if
や@foreach
といったRazorディレクティブの詳細を知りたい方は公式ドキュメントをご覧ください。
イベントを処理する
UI 要素からイベントのイベント コールバックを指定するには、@on で始まり、イベント名で終わる属性を使用します。
@onclick
@onchange
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount += 1; } }
<input @onchange="InputChanged" /> <p>@message</p> @code { string message = ""; void InputChanged(ChangeEventArgs e) { message = (string)e.Value; } }
データバインディング
UI要素の値が変更されたときにコードの値も変更され、コードの値が変更されたときにUI要素の表示も変わる、双方向データバインディングを設定するには@bind
属性を利用します。
<input @bind="text" /> <button @onclick="() => text = string.Empty">Clear</button> <p>@text</p> @code { string text = ""; }
TODOリスト作成
<!-- Todo.razor (Pages以下に配置) --> @page "/todo" @rendermode InteractiveServer <h3>Todo (@todos.Count(todo => !todo.IsDone))</h3> <ul> @foreach (var todo in todos) { <li> <input type="checkbox" @bind="todo.IsDone" /> <input @bind="todo.Title" /> </li> } </ul> <input @bind="newTodo" /> <button @onclick=AddTodo>Add todo</button> @code { private List<TodoItem> todos = new(); string newTodo = ""; void AddTodo() { if (!string.IsNullOrWhiteSpace(newTodo)) { todos.Add(new TodoItem { Title = newTodo }); newTodo = string.Empty; } } }
// TodoItem.cs (プロジェクトルートに配置) public class TodoItem { public string? Title { get; set; } public bool IsDone { get; set; } = false; }
さいごに
ひとまずBlazorをしようしたWeb開発の概要 ~ Blazorを使用してTODOリストを作成する
までやりました。気が向いたらこの先も進みたいと思います。