在 ASP.NET Core Blazor Hybrid 中重用 Razor 组件
注意
此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
本文介绍如何在 Blazor Hybrid 应用中创作和组织 Web 和 Web Views 的 Razor 组件。
Razor 组件可跨托管模型(Blazor WebAssembly、Blazor Server 以及在 Blazor Hybrid 的 Web View 中)和跨平台(Android、iOS 和 Windows)工作。 托管模型和平台具有组件可以利用的独特功能,但跨托管模型和平台执行的组件必须单独利用独特的功能,以下示例说明了这一点:
- Blazor WebAssembly 支持同步 JavaScript (JS) 互操作,而 Blazor Hybrid 应用的 Blazor Server 和 Web Views 中严格异步的 JS 互操作通信通道不支持此操作。
- Blazor Server 应用中的组件可以访问仅在服务器上可用的服务,例如实体框架数据库上下文。
BlazorWebView
中的组件可以直接访问本机本地桌面和移动设备功能,例如地理位置服务。 Blazor Server 和 Blazor WebAssembly 应用必须依赖外部服务器上应用程序的 Web API 接口来提供类似的功能。
设计原理
若要创作可跨托管模型和平台无缝工作的 Razor 组件,请遵循以下设计原则:
- 将共享 UI 代码放置在 Razor 类库 (RCL) 中,这些类库是容器,旨在维护可重用的 UI 片段,以便在不同的托管模型和平台上使用。
- RCL 中不应存在唯一功能的实现。 相反,RCL 应定义托管模型和平台实现的抽象(接口和基类)。
- 仅通过托管模型或平台选择加入独特功能。 例如,Blazor WebAssembly 支持在组件中使用 IJSInProcessRuntime 和 IJSInProcessObjectReference 作为优化,但仅将它们与依赖于所有托管模型和平台支持的通用 IJSRuntime 和 IJSObjectReference 抽象的条件转换和回退实现一起使用。 有关 IJSInProcessRuntime 的详细信息,请参阅在 ASP.NET Core Blazor 中从 .NET 方法调用 JavaScript 函数。 有关 IJSInProcessObjectReference 的详细信息,请参阅在 ASP.NET Core Blazor 中从 JavaScript 函数调用 .NET 方法。
- 作为一般规则,在组件中使用 CSS 进行 HTML 样式设置。 最常见的情况是应用的外观保持一致。 在 UI 样式必须在托管模型或平台之间有所不同的地方,使用 CSS 来设置不同的样式。
- 如果 UI 的某些部分需要针对目标托管模型或平台的其他或不同内容,则可以将内容封装在组件内并使用
DynamicComponent
在 RCL 内呈现。 还可以通过 RenderFragment 实例向组件提供其他 UI。 有关 RenderFragment 的详细信息,请参阅子内容呈现片段和可重用呈现逻辑的呈现片段。
项目代码组织
尽可能多地将代码和静态内容放在 Razor 类库 (RCL) 中。 每个托管模型或平台都引用 RCL,并在应用的服务集合中注册 Razor 组件可能需要的各个实现。
每个目标程序集应仅包含特定于该托管模型或平台的代码以及帮助启动应用的代码。
对独特的功能使用抽象
以下示例演示如何通过托管模型和平台对地理位置服务使用抽象。
- 在应用用来获取用户在地图上位置的地理位置数据的 Razor 类库 (RCL) 中,
MapComponent
Razor 组件会注入一个ILocationService
服务抽象。 - Blazor WebAssembly 和 Blazor Server 项目的
App.Web
将ILocationService
实现为WebLocationService
,它使用 Web API 调用来获取地理位置数据。 App.Desktop
对于 .NET MAUI、WPF 和 Windows 窗体,将ILocationService
实现为DesktopLocationService
。DesktopLocationService
使用特定于平台的设备功能来获取地理位置数据。
.NET MAUIBlazor 特定于平台的代码
.NET MAUI 中的一个常见模式是为不同平台创建单独的实现,例如使用特定于平台的实现定义部分类。 例如,请参阅下图,其中 CameraService
的部分类在 CameraService.Windows.cs
、CameraService.iOS.cs
、CameraService.Android.cs
和 CameraService.cs
中实现:
如果要将特定于平台的功能打包到可供其他应用使用的类库中,建议采用与前面示例中所述的方法类似的方法,并为 Razor 组件创建一个抽象:
- 将组件放置在 Razor 类库 (RCL) 中。
- 从 .NET MAUI 类库中,引用 RCL 并创建特定于平台的实现。
- 在消耗应用中,引用 .NET MAUI 类库。
以下示例演示了用于组织照片的应用中图像的概念:
- .NET MAUIBlazor Hybrid 应用使用其引用的 RCL 中的
InputPhoto
。 - .NET MAUI 应用还引用 .NET MAUI 类库。
- RCL 中的
InputPhoto
注入了一个在 RCL 中定义的ICameraService
接口。 ICameraService
的CameraService
部分类实现位于引用 RCL 的 .NET MAUI 类库(CameraService.Windows.cs
、CameraService.iOS.cs
、CameraService.Android.cs
)中。