在 JavaScript 应用和 SPA 框架中使用 Razor 组件

注意

此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

对于当前版本,请参阅此文的 .NET 8 版本

本文介绍如何从 JavaScript 呈现 Razor 组件、使用 Blazor 自定义元素,以及生成 Angular 和 React 组件。

Angular 示例应用

从 JavaScript 呈现 Razor 组件

可以从 JavaScript (JS) 为现有 JS 应用动态呈现 Razor 组件。

本部分中的示例通过 JS 将以下 Razor 组件呈现到页面中。

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包含一个重载,该重载接受执行初始化逻辑 (javaScriptInitializer) 的 JS 函数的名称。 在 Blazor 应用启动后和任何组件呈现之前,每次组件注册时都会立即调用 JS 函数一次。 此函数可用于与 JS 技术(如 HTML 自定义元素或基于 JS 的 SPA 框架)集成。

可以通过不同的组件注册创建和调用一个或多个初始值设定项函数。 典型的用例是为多个组件重复使用同一个初始值设定项函数,如果初始值设定项函数是要配置与自定义元素或其他基于 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 文件中的 RootComponents 上调用 RegisterForJavaScript

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

使用 nameparameters 函数参数将初始值设定项函数附加到 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.'"
    });
}

注意

要调用 rootComponents.add,请使用 Blazor 启动事件提供的 blazor 参数(小写的 b)。 尽管在使用 Blazor 对象(大写的 B)时注册有效,但首选方法是使用参数。

有关具有更多功能的高级示例,请参阅 ASP.NET Core 参考源中的 BasicTestApp 示例(dotnet/aspnetcore GitHub 存储库):

注意

指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)

Blazor 自定义元素

使用 Blazor 自定义元素从其他 SPA 框架(如 Angular 或 React)动态呈现 Razor 组件。

Blazor 自定义元素:

  • 使用标准 HTML 接口来实现自定义 HTML 元素。
  • 无需使用 JavaScript API 手动管理根 Razor 组件的状态和生命周期。
  • 可用于逐步将 Razor 组件引入到用其他 SPA 框架编写的现有项目中。

自定义元素不支持子内容模板化组件

元素名称

根据 HTML 规范,自定义元素标记名称必须采用 kebab 大小写形式:

无效:mycounter
无效:MY-COUNTER
无效:MyCounter
有效:my-counter
有效:my-cool-counter

程序包

向应用的项目文件添加 Microsoft.AspNetCore.Components.CustomElements 的包引用。

注意

有关将包添加到 .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++;
    }
}

Blazor Web 应用注册

执行以下步骤,将根组件注册为 Blazor Web 应用中的自定义元素。

Microsoft.AspNetCore.Components.Web 命名空间添加到服务器端 Program 文件的顶部:

using Microsoft.AspNetCore.Components.Web;

为应用的组件添加命名空间。 在以下示例中,应用的命名空间为 BlazorSample,且组件位于 Components/Pages 文件夹中:

using BlazorSample.Components.Pages;

修改对 AddInteractiveServerComponents 的调用,以使用 RootComponents 线路选项上的 RegisterCustomElement 指定自定义元素。 以下示例将 Counter 组件注册到自定义 HTML 元素 my-counter

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

Blazor Server 注册

执行以下步骤,将根组件注册为 Blazor Server 应用中的自定义元素。

Microsoft.AspNetCore.Components.Web 命名空间添加到 Program 文件的顶部:

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.Web 命名空间添加到 Program 文件的顶部:

using Microsoft.AspNetCore.Components.Web;

为应用的组件添加命名空间。 在以下示例中,应用的命名空间为 BlazorSample,且组件位于 Pages 文件夹中:

using BlazorSample.Pages;

RootComponents 上调用 RegisterCustomElement。 以下示例将 Counter 组件注册到自定义 HTML 元素 my-counter

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

使用已注册的自定义元素

将自定义元素与任何 Web 框架结合使用。 例如,前面用于呈现应用的 Counter 组件的 my-counter 自定义 HTML 元素在 React 应用中使用的标记如下:

<my-counter></my-counter>

有关如何使用 Blazor创建自定义元素的完整示例,请参阅参考源中的 CustomElementsComponent 组件

注意

指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 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 组件,并将值作为 HTML 属性传递给 IncrementAmount 参数。 属性名称采用 kebab 大小写语法(increment-amount,不是 IncrementAmount):

<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 应用中,修改对 Program 文件中 AddServerSideBlazor 的调用来调用 CircuitOptions.RootComponents 上的 RegisterCustomElement

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

    注意

    前面的代码示例要求在 Program 文件中为应用的组件(例如 using BlazorSample.Components.Pages;)提供一个命名空间。

  • 在 Blazor WebAssembly 应用中,在 Program 文件中的 WebAssemblyHostBuilder.RootComponents 上调用 RegisterCustomElement

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

    注意

    前面的代码示例要求在 Program 文件中为应用的组件(例如 using BlazorSample.Components.Pages;)提供一个命名空间。

在应用的 HTML 中在Blazor 脚本标记之前添加以下 <script> 标记:

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

将自定义元素与任何 Web 框架结合使用。 例如,前面的 counter 自定义元素在带有以下标记的 React 应用中使用:

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

警告

自定义元素功能目前处于实验阶段,不受支持,并且随时可能更改或删除。 欢迎你就这种特定方法能否满足你的要求提出反馈意见。

生成 Angular 和 React 组件

通过 Razor 组件为 Web 框架生成特定于框架的 JavaScript (JS) 组件,例如 Angular 或 React。 此功能未包含在 .NET 中,但通过支持(即,支持从 JS 呈现 Razor 组件)得以实现。 GitHub 上的JS 组件生成示例演示了如何通过 Razor 组件生成 Angular 和 React 组件。 有关其他信息,请参阅 GitHub 示例应用的 README.md 文件。

警告

Angular 和 React 组件功能目前处于实验阶段,不受支持,并且随时可能更改或删除。 欢迎你就这种特定方法能否满足你的要求提出反馈意见。