JavaScript アプリと SPA フレームワークで Razor コンポーネントを使用する

注意

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

この記事では、JavaScript から Razor コンポーネントをレンダリングし、Blazor カスタム要素を使用し、Angular および React コンポーネントを生成する方法について説明します。

Angular サンプル アプリ

JavaScript から Razor コンポーネントをレンダリングする

Razor コンポーネントは、既存の JavaScript (JS) アプリの JS から動的にレンダリングできます。

このセクションの例では、次の Razor コンポーネントを JS を使ってページにレンダリングします。

Quote.razor:

<div class="m-5 p-5">
    <h2>Quote</h2>
    <p>@Text</p>
</div>

@code {
    [Parameter]
    public string? Text { get; set; }
}

Program ファイルに、コンポーネントの場所の名前空間を追加します。

アプリのルート コンポーネント コレクションで RegisterForJavaScript を呼び出し、Razor コンポーネントを JS レンダリング用のルート コンポーネントとして登録します。

RegisterForJavaScript には、初期化ロジックを実行する JS 関数の名前 (javaScriptInitializer) を受け取るオーバーロードが含まれています。 この JS 関数は、Blazor アプリの起動直後、コンポーネントがレンダリングされる前に、コンポーネント登録ごとに 1 回呼び出されます。 この関数は、JS テクノロジとの統合のために使用できます。たとえば、HTML カスタム要素や JS ベースの SPA フレームワークなどです。

1 つ以上の初期化子関数を作成し、さまざまなコンポーネント登録によって呼び出すことができます。 一般的なユース ケースは、複数のコンポーネントに対して同じ初期化子関数を再利用することです。これは、初期化子関数がカスタム要素や、別の JS ベースの SPA フレームワークとの統合を構成している場合に想定されます。

重要

RegisterForJavaScriptjavaScriptInitializer パラメーターを JavaScript 初期化子と混同しないでください。 このパラメーターと JS の初期化子機能の名前はたまたま同じです。

次の例では、識別子として "quote" を持つ前の Quote コンポーネントの動的登録を示します。

  • Blazor Web アプリで、サーバー側 Program ファイル内の AddInteractiveServerComponents への呼び出しを変更します。

    builder.Services.AddRazorComponents()
        .AddInteractiveServerComponents(options =>
        {
            options.RootComponents.RegisterForJavaScript<Quote>(identifier: "quote",
              javaScriptInitializer: "initializeComponent");
        });
    
  • Blazor Server アプリで、Program ファイル内の AddServerSideBlazor への呼び出しを変更します。

    builder.Services.AddServerSideBlazor(options =>
    {
        options.RootComponents.RegisterForJavaScript<Quote>(identifier: "quote", 
            javaScriptInitializer: "initializeComponent");
    });
    
  • Blazor WebAssembly アプリで、クライアント側の Program ファイル内の RootComponentsRegisterForJavaScript を呼び出します。

    builder.RootComponents.RegisterForJavaScript<Quote>(identifier: "quote", 
        javaScriptInitializer: "initializeComponent");
    

name および parameters 関数パラメーターを持つ初期化子関数を window オブジェクトにアタッチします。 次の initializeComponent 関数は、デモのために、登録されているコンポーネントの名前とパラメーターをログします。

wwwroot/jsComponentInitializers.js:

window.initializeComponent = (name, parameters) => {
  console.log({ name: name, parameters: parameters });
}

登録された識別子を使って JS からコンテナー要素にコンポーネントをレンダリングし、必要に応じてコンポーネント パラメーターを渡します。

次に例を示します。

  • showQuote 関数が呼び出されると、Quote コンポーネント (quote 識別子) が quoteContainer 要素にレンダリングされます。
  • 引用文字列がコンポーネントの Text パラメーターに渡されます。

wwwroot/scripts.js:

async function showQuote() {
  let targetElement = document.getElementById('quoteContainer');
  await Blazor.rootComponents.add(targetElement, 'quote', 
  {
    text: "Crow: I have my doubts that this movie is actually 'starring' " +
      "anybody. More like, 'camera is generally pointed at.'"
  });
}

Blazor スクリプトが読み込まれたら、前のスクリプトを JS アプリに読み込みます。

<script src="_framework/{BLAZOR SCRIPT}"></script>
<script src="jsComponentInitializers.js"></script>
<script src="scripts.js"></script>

前の例では、{BLAZOR SCRIPT} プレースホルダーが Blazor スクリプトです。

HTML で、ターゲット コンテナー要素 (quoteContainer) を配置します。 このセクションのデモでは、ボタンによって showQuoteJS 関数を呼び出すことで Quote コンポーネントのレンダリングがトリガーされます。

<button onclick="showQuote()">Show Quote</button>

<div id="quoteContainer"></div>

コンポーネントがレンダリングされる前の初期化時に、ブラウザーの開発者ツール コンソールでは、initializeComponent が呼び出されたときに Quote コンポーネントの識別子 (name) とパラメーター (parameters) がログされます。

Object { name: "quote", parameters: (1) […] }
  name: "quote"
  parameters: Array [ {…} ]
    0: Object { name: "Text", type: "string" }
    length: 1

Show Quote ボタンを選択すると、Quote コンポーネントがレンダリングされ、Text に格納されている引用が表示されます。

ブラウザーにレンダリングされる引用

引用 ©1988-1999 Satellite of Love LLC: Mystery Science Theater 3000 (Trace Beaulieu (Crow))

注意

rootComponents.add はコンポーネントのインスタンスを返します。 インスタンスで dispose を呼び出して解放します。

const rootComponent = await window.Blazor.rootComponents.add(...);

...

rootComponent.dispose();

前述の例では、showQuote()JS 関数が呼び出されたときにルート コンポーネントを動的にレンダリングします。 Blazor の起動時にルート コンポーネントをコンテナー要素にレンダリングするには、次の例に示すように、JavaScript 初期化子を使用してそのコンポーネントをレンダリングします。

次の例は、前述の例、Quote コンポーネントの使用、Program ファイルでのルート コンポーネントの登録、jsComponentInitializers.js の初期化の上に構築されています。 showQuote() 関数 (と script.js ファイル) は使用されません。

HTML で、ターゲット コンテナー要素 (この例では quoteContainer2) を配置します。

<div id="quoteContainer2"></div>

JavaScript 初期化子を使用して、ルート コンポーネントをターゲット コンテナー要素に追加します。

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js:

Blazor Web アプリの場合:

export function afterWebStarted(blazor) {
  let targetElement = document.getElementById('quoteContainer2');
  blazor.rootComponents.add(targetElement, 'quote',
    {
      text: "Crow: I have my doubts that this movie is actually 'starring' " +
          "anybody. More like, 'camera is generally pointed at.'"
    });
}

Blazor Server または Blazor WebAssembly アプリの場合:

export function afterStarted(blazor) {
  let targetElement = document.getElementById('quoteContainer2');
  blazor.rootComponents.add(targetElement, 'quote',
    {
      text: "Crow: I have my doubts that this movie is actually 'starring' " +
          "anybody. More like, 'camera is generally pointed at.'"
    });
}

Note

rootComponents.add の呼び出しには、Blazor 開始イベントによって提供される blazor パラメーター (b は小文字) を使用します。 Blazor オブジェクト (B は大文字) を使用しても登録は有効ですが、パラメーターを使用することをお勧めします。

追加機能を備えた高度な例については、ASP.NET Core リファレンス ソース (dotnet/aspnetcore GitHub リポジトリ) の BasicTestApp の例を参照してください。

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

Blazor カスタム要素

Blazor カスタム要素を使って、Angular や React など、他の SPA フレームワークから Razor コンポーネントを動的にレンダリングします。

Blazor カスタム要素は:

  • 標準の HTML インターフェイスを使用してカスタム HTML 要素を実装します。
  • JavaScript API を使ってルート Razor コンポーネントの状態とライフサイクルを手動で管理する必要はありません。
  • 他の SPA フレームワークで記述された既存のプロジェクトに Razor コンポーネントを段階的に導入する場合に便利です。

カスタム要素では、子コンテンツテンプレート コンポーネントはサポートされていません。

要素名

HTML の仕様に従って、カスタム要素のタグ名はケバブ ケースにする必要があります。

無効:mycounter
無効:MY-COUNTER
無効:MyCounter
有効:my-counter
有効:my-cool-counter

パッケージ

アプリのプロジェクト ファイルに、Microsoft.AspNetCore.Components.CustomElements のパッケージ参照を追加します。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

コンポーネントの例

次の例は、Blazor プロジェクト テンプレートの Counter コンポーネントに基づいています。

Counter.razor:

@page "/counter"

<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++;
    }
}

BlazorWeb アプリの登録

ルート コンポーネントをカスタム要素として Blazor Web アプリに登録するには、次の手順を行います。

名前空間 Microsoft.AspNetCore.Components.Web をサーバー側の Program ファイルの先頭に追加します。

using Microsoft.AspNetCore.Components.Web;

アプリのコンポーネント用の名前空間を追加します。 次の例では、アプリの名前空間は BlazorSample です。コンポーネントは Components/Pages フォルダー内に置かれます。

using BlazorSample.Components.Pages;

RootComponents 回線オプションに対して RegisterCustomElement を使用してカスタム要素を指定するように、AddInteractiveServerComponents の呼び出しを変更します。 次の例では、Counter コンポーネントをカスタム HTML 要素 my-counter に登録します。

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents(options =>
    {
        options.RootComponents.RegisterCustomElement<Counter>("my-counter");
    });

Blazor Server の登録

ルート コンポーネントをカスタム要素として Blazor Server アプリに登録するには、次の手順を行います。

名前空間 Microsoft.AspNetCore.Components.WebProgram ファイルの先頭に追加します。

using Microsoft.AspNetCore.Components.Web;

アプリのコンポーネント用の名前空間を追加します。 次の例では、アプリの名前空間は BlazorSample です。コンポーネントは Pages フォルダー内に置かれます。

using BlazorSample.Pages;

AddServerSideBlazor の呼び出しを変更します。 RootComponents 回線オプションに対して RegisterCustomElement を使用してカスタム要素を指定します。 次の例では、Counter コンポーネントをカスタム HTML 要素 my-counter に登録します。

builder.Services.AddServerSideBlazor(options =>
{
    options.RootComponents.RegisterCustomElement<Counter>("my-counter");
});

Blazor WebAssembly の登録

ルート コンポーネントをカスタム要素として Blazor WebAssembly アプリに登録するには、次の手順を行います。

名前空間 Microsoft.AspNetCore.Components.WebProgram ファイルの先頭に追加します。

using Microsoft.AspNetCore.Components.Web;

アプリのコンポーネント用の名前空間を追加します。 次の例では、アプリの名前空間は BlazorSample です。コンポーネントは Pages フォルダー内に置かれます。

using BlazorSample.Pages;

RootComponentsRegisterCustomElement を呼び出します。 次の例では、Counter コンポーネントをカスタム HTML 要素 my-counter に登録します。

builder.RootComponents.RegisterCustomElement<Counter>("my-counter");

登録済みのカスタム要素を使う

任意の Web フレームワークでカスタム要素を使用します。 たとえば、アプリの Counter コンポーネントをレンダリングする上記の my-counter カスタム HTML 要素は、React アプリで次のマークアップによって使用されます。

<my-counter></my-counter>

Blazor でカスタム要素を作成する方法の完全な例については、リファレンス ソースの CustomElementsComponent コンポーネントに関するページを参照してください。

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

パラメーターを渡す

パラメーターを、HTML 属性として、または DOM 要素の JavaScript プロパティとして、Razor コンポーネントに渡します。

次の Counter コンポーネントでは、IncrementAmount パラメーターを使って、Click me ボタンの増分量を設定しています。

Counter.razor:

@page "/counter"

<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]
    public int IncrementAmount { get; set; } = 1;

    private void IncrementCount()
    {
        currentCount += IncrementAmount;
    }
}

カスタム要素を使って Counter コンポーネントをレンダリングし、IncrementAmount パラメーターに HTML 属性として値を渡します。 属性名はケバブケースの構文にします (IncrementAmount ではなく increment-amount)。

<my-counter increment-amount="10"></my-counter>

または、要素オブジェクトの JavaScript プロパティとしてパラメーターの値を設定することもできます。 プロパティ名はキャメル ケースの構文にします (IncrementAmount ではなく incrementAmount)。

const elem = document.querySelector("my-counter");
elem.incrementAmount = 10;

パラメーター値は、属性またはプロパティ構文を使っていつでも更新できます。

サポートされているパラメーターの種類:

  • JavaScript プロパティ構文を使う場合は、JSON シリアル化可能な任意の型のオブジェクトを渡すことができます。
  • HTML 属性を使う場合は、文字列型、ブール型、または数値型のオブジェクトだけを渡すことができます。

Microsoft.AspNetCore.Components.CustomElements NuGet パッケージを使用してカスタム要素を構築する場合は、"実験的" サポートを利用できます。 カスタム要素では、標準の HTML インターフェイスを使用してカスタム HTML 要素を実装します。

警告

試験段階の機能は、機能の有効性を調べる目的で提供されており、安定バージョンには含まれていない場合があります。

ルート コンポーネントをカスタム要素として登録します。

  • Blazor Server アプリで、CircuitOptions.RootComponentsRegisterCustomElement を呼び出すために、Program ファイル内の AddServerSideBlazor への呼び出しを変更します。

    builder.Services.AddServerSideBlazor(options =>
    {
        options.RootComponents.RegisterCustomElement<Counter>("my-counter");
    });
    

    Note

    上記のコード例では、Program ファイル内のアプリのコンポーネント (たとえば、using BlazorSample.Components.Pages;) の名前空間が必要です。

  • Blazor WebAssembly アプリで、Program ファイル内の WebAssemblyHostBuilder.RootComponentsRegisterCustomElement を呼び出します。

    builder.RootComponents.RegisterCustomElement<Counter>("my-counter");
    

    Note

    上記のコード例では、Program ファイル内のアプリのコンポーネント (たとえば、using BlazorSample.Components.Pages;) の名前空間が必要です。

アプリの HTML の Blazor スクリプト タグの "" に、次の <script> タグを含めます。

<script src="/_content/Microsoft.AspNetCore.Components.CustomElements/BlazorCustomElements.js"></script>

任意の Web フレームワークでカスタム要素を使用します。 たとえば、上記のカウンター カスタム要素は、次のマークアップと共に React アプリで使用されます。

<my-counter increment-amount={incrementAmount}></my-counter>

警告

カスタム要素機能は現在試験段階で、サポートされていないため、いつでも変更または削除される可能性があります。 この特定のアプローチが要件をどの程度満たすかについてフィードバックをお寄せください。

Angular コンポーネントと React コンポーネントを生成する

Angular や React などの Web フレームワークの Razor コンポーネントから、フレームワーク固有の JavaScript (JS) コンポーネントを生成します。 この機能は .NET には含まれていませんが、JS から Razor コンポーネントをレンダリングするサポートによって有効になります。 GitHub の JS コンポーネント生成サンプルは、Razor コンポーネントから Angular コンポーネントと React コンポーネントを生成する方法を示しています。 詳細については、GitHub サンプル アプリの README.md ファイルを参照してください。

警告

Angular コンポーネントと React コンポーネントの機能は現在試験段階で、サポートされていないため、いつでも変更または削除される可能性があります。 この特定のアプローチが要件をどの程度満たすかについてフィードバックをお寄せください。