最初の Blazor アプリをビルドするBuild your first Blazor app

作成者: Daniel RothLuke LathamBy Daniel Roth and Luke Latham

重要

プレビュー段階の Blazor WebAssemblyBlazor WebAssembly in preview

Blazor サーバーは ASP.NET Core 3.0 でサポートされています。Blazor Server is supported in ASP.NET Core 3.0. Blazor WebAssembly は、ASP.NET Core 3.1 のプレビュー段階です。Blazor WebAssembly is in preview for ASP.NET Core 3.1.

このチュートリアルでは、Blazor アプリをビルドして変更する方法を示します。This tutorial shows you how to build and modify a Blazor app.

ASP.NET Core Blazor の概要 の記事にあるガイダンスに従って、このチュートリアルの Blazor プロジェクトを作成します。Follow the guidance in the ASP.NET Core Blazor の概要 article to create a Blazor project for this tutorial. プロジェクトに ToDoList という名前を付けます。Name the project ToDoList.

コンポーネントを構築するBuild components

  1. Pages フォルダー内にあるアプリの 3 つのページそれぞれを参照します。ホーム、カウンター、データのフェッチです。Browse to each of the app's three pages in the Pages folder: Home, Counter, and Fetch data. これらのページは Razor コンポーネント ファイル Index.razorCounter.razor、および FetchData.razor によって実装されています。These pages are implemented by the Razor component files Index.razor, Counter.razor, and FetchData.razor.

  2. Counter ページ上で [クリックしてください] ボタンを選択し、ページを更新することなくカウンターをインクリメントします。On the Counter page, select the Click me button to increment the counter without a page refresh. Web ページでカウンターをインクリメントする場合、通常は JavaScript を記述することが必要です。Incrementing a counter in a webpage normally requires writing JavaScript. Blazor を使用すると、代わりに C# を記述できます。With Blazor, you can write C# instead.

  3. Counter.razor ファイルで Counter コンポーネントの実装を調べます。Examine the implementation of the Counter component in the Counter.razor file.

    Pages/Counter.razor:Pages/Counter.razor:

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Counter コンポーネントの UI は、HTML を使って定義されています。The UI of the Counter component is defined using HTML. 動的なレンダリング ロジック (たとえばループ、条件、式) が、Razor と呼ばれる埋め込みの C# 構文を使って追加されています。Dynamic rendering logic (for example, loops, conditionals, expressions) is added using an embedded C# syntax called Razor. HTML マークアップと C# のレンダリング ロジックは、ビルド時にコンポーネント クラスに変換されます。The HTML markup and C# rendering logic are converted into a component class at build time. 生成される .NET クラスの名前はファイル名と同じです。The name of the generated .NET class matches the file name.

    コンポーネント クラスのメンバーは、@code ブロック内で定義されています。Members of the component class are defined in an @code block. @code ブロック内では、イベント処理や他のコンポーネント ロジックの定義のために、コンポーネントの状態 (プロパティ、フィールド) とメソッドを指定します。In the @code block, component state (properties, fields) and methods are specified for event handling or for defining other component logic. これらのメンバーは、コンポーネントのレンダリング ロジックの一部として、またイベントを処理するために使われます。These members are then used as part of the component's rendering logic and for handling events.

    [クリックしてください] ボタンを選択すると:When the Click me button is selected:

    • Counter コンポーネントの登録済みの onclick ハンドラーが呼び出されます (IncrementCount メソッドです)。The Counter component's registered onclick handler is called (the IncrementCount method).
    • Counter コンポーネントによりそのレンダリング ツリーが再生成されます。The Counter component regenerates its render tree.
    • 新しいレンダリング ツリーが以前のものと比較されます。The new render tree is compared to the previous one.
    • ドキュメント オブジェクト モデル (DOM) に対する変更のみが適用されます。Only modifications to the Document Object Model (DOM) are applied. 表示されている数が更新されます。The displayed count is updated.
  4. Counter コンポーネントの C# のロジックを変更して、カウントが 1 ではなく 2 ずつインクリメントされるようにします。Modify the C# logic of the Counter component to make the count increment by two instead of one.

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount += 2;
        }
    }
    
  5. アプリをリビルドして実行し、変更を確認します。Rebuild and run the app to see the changes. [クリックしてください] ボタンを選択します。Select the Click me button. カウンターは、2 ずつインクリメントされます。The counter increments by two.

コンポーネントを使うUse components

HTML 構文を使用して、別のコンポーネント内にコンポーネントを含めます。Include a component in another component using an HTML syntax.

  1. Index コンポーネント (Index.razor) に <Counter /> 要素を追加することで、アプリの Index コンポーネントに Counter コンポーネントを追加します。Add the Counter component to the app's Index component by adding a <Counter /> element to the Index component (Index.razor).

    このエクスペリエンスのために Blazor WebAssembly を使用している場合、SurveyPrompt コンポーネントによって Index コンポーネントが使用されます。If you're using Blazor WebAssembly for this experience, a SurveyPrompt component is used by the Index component. <SurveyPrompt> 要素を <Counter /> 要素に置き換えます。Replace the <SurveyPrompt> element with a <Counter /> element. このエクスペリエンスに Blazor サーバー アプリを使用している場合は、<Counter /> 要素を Index コンポーネントに追加します。If you're using a Blazor Server app for this experience, add the <Counter /> element to the Index component:

    Pages/Index.razor:Pages/Index.razor:

    @page "/"
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <Counter />
    
  2. アプリケーションをリビルドして実行します。Rebuild and run the app. Index コンポーネントには、固有のカウンターがあります。The Index component has its own counter.

コンポーネントのパラメーターComponent parameters

コンポーネントにパラメーターを持たせることもできます。Components can also have parameters. コンポーネントのパラメーターは、[Parameter] 属性が指定されたコンポーネント クラス上で、パブリック プロパティを使用して定義されます。Component parameters are defined using public properties on the component class with the [Parameter] attribute. マークアップ内でコンポーネントの引数を指定するには、属性を使います。Use attributes to specify arguments for a component in markup.

  1. コンポーネントの @code に関する C# コードを更新します。Update the component's @code C# code:

    • 属性 [Parameter] を使用してパブリック IncrementAmount プロパティを追加します。Add a public IncrementAmount property with the [Parameter] attribute.
    • currentCount の値を増やすときに IncrementAmount を使うように IncrementCount メソッドを変更します。Change the IncrementCount method to use the IncrementAmount when increasing the value of currentCount.

    Pages/Counter.razor:Pages/Counter.razor:

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        [Parameter]
        public int IncrementAmount { get; set; } = 1;
    
        private void IncrementCount()
        {
            currentCount += IncrementAmount;
        }
    }
    
  1. 属性を使って、Index コンポーネントの <Counter> 要素に IncrementAmount パラメーターを指定します。Specify an IncrementAmount parameter in the Index component's <Counter> element using an attribute. カウンターを 10 ずつインクリメントするように値を設定します。Set the value to increment the counter by ten.

    Pages/Index.razor:Pages/Index.razor:

    @page "/"
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <Counter IncrementAmount="10" />
    
  2. Index コンポーネントを再度読み込みます。Reload the Index component. カウンターは、 [クリックしてください] ボタンを選択するたびに 10 ずつインクリメントされます。The counter increments by ten each time the Click me button is selected. Counter コンポーネントにあるカウンターは、継続して 1 ずつインクリメントされます。The counter in the Counter component continues to increment by one.

コンポーネントにルーティングするRoute to components

Counter.razor ファイルの上部にある @page ディレクティブは、Counter コンポーネントがルーティング エンドポイントであることを指定しています。The @page directive at the top of the Counter.razor file specifies that the Counter component is a routing endpoint. Counter コンポーネントによって /counter に送信された要求が処理されます。The Counter component handles requests sent to /counter. @page ディレクティブがない場合、ルーティングされた要求はコンポーネントでは処理されませんが、そのコンポーネントは他のコンポーネントから引き続き使用できます。Without the @page directive, a component doesn't handle routed requests, but the component can still be used by other components.

依存関係の挿入Dependency injection

Blazor サーバーのエクスペリエンス Server experience

Blazor サーバー アプリを使用している場合、WeatherForecastService サービスは Startup.ConfigureServicesシングルトンとして登録されます。If working with a Blazor Server app, the WeatherForecastService service is registered as a singleton in Startup.ConfigureServices. サービスのインスタンスは、依存関係の挿入 (DI) を介してアプリ全体で利用できます。An instance of the service is available throughout the app via dependency injection (DI):

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddSingleton<WeatherForecastService>();
}

FetchData コンポーネントに WeatherForecastService サービスのインスタンスを挿入するために、@inject ディレクティブが使われています。The @inject directive is used to inject the instance of the WeatherForecastService service into the FetchData component.

Pages/FetchData.razor:Pages/FetchData.razor:

@page "/fetchdata"
@using ToDoList.Data
@inject WeatherForecastService ForecastService

FetchData コンポーネントでは、ForecastService のような挿入されたサービスを使って、WeatherForecast オブジェクトの配列を取得します。The FetchData component uses the injected service, as ForecastService, to retrieve an array of WeatherForecast objects:

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
}

Blazor WebAssembly のエクスペリエンス WebAssembly experience

Blazor WebAssembly アプリを使用する場合、wwwroot/sample-data フォルダー内の weather.json ファイルから天気予報データを取得するために、HttpClient が挿入されます。If working with a Blazor WebAssembly app, HttpClient is injected to obtain weather forecast data from the weather.json file in the wwwroot/sample-data folder.

Pages/FetchData.razor:Pages/FetchData.razor:

@inject HttpClient Http

...

protected override async Task OnInitializedAsync()
{
    forecasts = 
        await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}

各 forecast 変数を気象データのテーブルの行としてレンダリングするために、@foreach ループが使われています。An @foreach loop is used to render each forecast instance as a row in the table of weather data:

<table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var forecast in forecasts)
        {
            <tr>
                <td>@forecast.Date.ToShortDateString()</td>
                <td>@forecast.TemperatureC</td>
                <td>@forecast.TemperatureF</td>
                <td>@forecast.Summary</td>
            </tr>
        }
    </tbody>
</table>

Todo リストを構築するBuild a todo list

シンプルな ToDo リストを実装したアプリに新しいコンポーネントを追加します。Add a new component to the app that implements a simple todo list.

  1. Pages フォルダー内のアプリに、Todo.razor という名前の空のファイルを追加します。Add an empty file named Todo.razor to the app in the Pages folder:

  2. コンポーネントに最初のマークアップを指定します。Provide the initial markup for the component:

    @page "/todo"
    
    <h1>Todo</h1>
    
  3. ナビゲーション バーに Todo コンポーネントを追加します。Add the Todo component to the navigation bar.

    アプリのレイアウトでは、NavMenu コンポーネント (Shared/NavMenu.csthml) が使用されます。The NavMenu component (Shared/NavMenu.razor) is used in the app's layout. レイアウトは、アプリ内でのコンテンツの重複を回避するために使うコンポーネントです。Layouts are components that allow you to avoid duplication of content in the app.

    Shared/NavMenu.csthml ファイル内で、既存のリスト アイテムの下に以下のリスト アイテムのマークアップを追加して、Todo コンポーネント用の <NavLink> 要素を追加します。Add a <NavLink> element for the Todo component by adding the following list item markup below the existing list items in the Shared/NavMenu.razor file:

    <li class="nav-item px-3">
        <NavLink class="nav-link" href="todo">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Todo
        </NavLink>
    </li>
    
  4. アプリケーションをリビルドして実行します。Rebuild and run the app. 新しい Todo ページに移動して、Todo コンポーネントへのリンクが機能することを確認します。Visit the new Todo page to confirm that the link to the Todo component works.

  5. Todo アイテムを表すクラスを保持するために、プロジェクトのルートに TodoItem.cs ファイルを追加します。Add a TodoItem.cs file to the root of the project to hold a class that represents a todo item. TodoItem クラス用に次の C# コードを使います。Use the following C# code for the TodoItem class:

    public class TodoItem
    {
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
    
  6. Todo コンポーネントに戻ります (Pages/Todo.razor)。Return to the Todo component (Pages/Todo.razor):

    • Todo 項目用のフィールドを @code ブロックに追加します。Add a field for the todo items in an @code block. Todo コンポーネントでは、このフィールドを使って ToDo リストの状態を維持します。The Todo component uses this field to maintain the state of the todo list.
    • 各 Todo アイテムをリスト アイテム (<li>) としてレンダリングするために、順序のないリストのマークアップと foreach ループを追加します。Add unordered list markup and a foreach loop to render each todo item as a list item (<li>).
    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
    }
    
  7. アプリには、リストに Todo 項目を追加するための UI 要素が必要です。The app requires UI elements for adding todo items to the list. 順序のないリスト (<ul>...</ul>) の下に、テキスト入力 (<input>) とボタン (<button>) を追加します。Add a text input (<input>) and a button (<button>) below the unordered list (<ul>...</ul>):

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    <input placeholder="Something todo" />
    <button>Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
    }
    
  8. アプリケーションをリビルドして実行します。Rebuild and run the app. [Add todo](ToDo の追加) ボタンを選択しても何も起こりません。ボタンにイベント ハンドラーが関連付けられていないためです。When the Add todo button is selected, nothing happens because an event handler isn't wired up to the button.

  9. Todo コンポーネントに AddTodo メソッドを追加し、@onclick 属性を使ってこれをボタンの選択用に登録します。Add an AddTodo method to the Todo component and register it for button selections using the @onclick attribute. ボタンを選択すると C# のメソッド AddTodo が呼び出されます。The AddTodo C# method is called when the button is selected:

    <input placeholder="Something todo" />
    <button @onclick="AddTodo">Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
    
        private void AddTodo()
        {
            // Todo: Add the todo
        }
    }
    
  10. 新しい Todo アイテムのタイトルを取得するために、@code ブロックの上部に文字列フィールド newTodo を追加し、<input> 要素の bind 属性を使ってこれをテキスト入力の値とバインドします。To get the title of the new todo item, add a newTodo string field at the top of the @code block and bind it to the value of the text input using the bind attribute in the <input> element:

    private IList<TodoItem> todos = new List<TodoItem>();
    private string newTodo;
    
    <input placeholder="Something todo" @bind="newTodo" />
    
  11. 指定したタイトルを備えた TodoItem をリストに追加するように、AddTodo メソッドを更新します。Update the AddTodo method to add the TodoItem with the specified title to the list. newTodo を空の文字列に設定して、テキスト入力の値をクリアします。Clear the value of the text input by setting newTodo to an empty string:

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    <input placeholder="Something todo" @bind="newTodo" />
    <button @onclick="AddTodo">Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
        private string newTodo;
    
        private void AddTodo()
        {
            if (!string.IsNullOrWhiteSpace(newTodo))
            {
                todos.Add(new TodoItem { Title = newTodo });
                newTodo = string.Empty;
            }
        }
    }
    
  12. アプリケーションをリビルドして実行します。Rebuild and run the app. Todo リストに Todo 項目をいくつか追加して、新しいコードをテストします。Add some todo items to the todo list to test the new code.

  13. 各 Todo アイテムのタイトルのテキストは編集可能にすることができます。また、チェック ボックスはユーザーが完了したアイテムを追跡するのに役立ちます。The title text for each todo item can be made editable, and a check box can help the user keep track of completed items. 各 Todo アイテムにチェック ボックス入力を追加し、その値を IsDone プロパティにバインドします。Add a check box input for each todo item and bind its value to the IsDone property. @todo.Title を、@todo.Title にバインドされた <input> 要素に変更します。Change @todo.Title to an <input> element bound to @todo.Title:

    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind="todo.IsDone" />
                <input @bind="todo.Title" />
            </li>
        }
    </ul>
    
  14. それらの値がバインドされていることを確認するために、<h1> ヘッダーを更新して、完了していない (IsDonefalse の) Todo アイテムの数のカウントを表示するようにします。To verify that these values are bound, update the <h1> header to show a count of the number of todo items that aren't complete (IsDone is false).

    <h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
    
  15. 完成した Todo コンポーネント (Pages/Todo.razor):The completed Todo component (Pages/Todo.razor):

    @page "/todo"
    
    <h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind="todo.IsDone" />
                <input @bind="todo.Title" />
            </li>
        }
    </ul>
    
    <input placeholder="Something todo" @bind="newTodo" />
    <button @onclick="AddTodo">Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
        private string newTodo;
    
        private void AddTodo()
        {
            if (!string.IsNullOrWhiteSpace(newTodo))
            {
                todos.Add(new TodoItem { Title = newTodo });
                newTodo = string.Empty;
            }
        }
    }
    
  16. アプリケーションをリビルドして実行します。Rebuild and run the app. Todo アイテムを追加して新しいコードをテストします。Add todo items to test the new code.