Blazor 基础入门
dotNET跨平台 今天
以下文章来源于amazingdotnet ,作者WeihanLi
Blazor 基础知识
Intro
Blazor 是微软在 .NET 里推出的一个 WEB 客户端 UI 交互的框架,
使用 Blazor 你可以代替 JavaScript 来实现自己的页面交互逻辑,可以很大程度上进行 C# 代码的复用,Blazor 对于 .NET 开发人员来说是一个不错的选择。
托管模型
Blazor 有两种托管模式,一种是 Blazor Server 模式,基于 asp.net core 部署,客户端和服务器的交互通过 SignalR 来完成,来实现客户端 UI 的更新和行为的交互。
![](http://pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL2ltYWdlMTA5LjM2MGRvYy5jbi9Eb3dubG9hZEltZy8yMDIxLzA2LzEwMTYvMjIzODkyODg1XzJfMjAyMTA2MTAwNDI1MDc4OTU=.jpg)
![](http://pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL2ltYWdlMTA5LjM2MGRvYy5jbi9Eb3dubG9hZEltZy8yMDIxLzA2LzEwMTYvMjIzODkyODg1XzNfMjAyMTA2MTAwNDI1MDg1MQ==.jpg)
另外一种是 Blazor WebAssembly 模式, 将 Blazor 应用、其依赖项以及 .NET 运行时下载到浏览器, 应用将在浏览器线程中直接执行。
![](http://n4.ikafan.com/assetsj/blank.gif)
![](http://n4.ikafan.com/assetsj/blank.gif)
两种模式各有优缺点,但是个人觉得 WebAssembly 模式的 Blazor 意义更大一些
Blazor Server 托管模型具有以下优点:
下载项大小明显小于 Blazor WebAssembly 应用,且应用加载速度快得多。 应用可充分利用服务器功能,包括使用任何与 .NET Core 兼容的 API。 服务器上的 .NET Core 用于运行应用,因此调试等现有 .NET 工具可按预期正常工作。 支持瘦客户端。例如,Blazor Server 应用适用于不支持 WebAssembly 的浏览器以及资源受限的设备。 应用的 .NET/C# 代码库(其中包括应用的组件代码)不适用于客户端。
Blazor Server 托管模型具有以下局限性:
通常延迟较高。每次用户交互都涉及到网络跃点。 不支持脱机工作。如果客户端连接失败,应用会停止工作。 如果具有多名用户,则应用扩缩性存在挑战。服务器必须管理多个客户端连接并处理客户端状态(SignalR)。 需要 ASP.NET Core 服务器为应用提供服务。无服务器部署方案不可行,例如通过内容分发网络 (CDN) 为应用提供服务的方案。
Blazor WebAssembly 托管模型具有以下优点:
没有 .NET 服务器端依赖,应用下载到客户端后即可正常运行。 可充分利用客户端资源和功能。 工作可从服务器转移到客户端。 无需 ASP.NET Core Web 服务器即可托管应用。无服务器部署方案可行,例如通过内容分发网络 (CDN) 为应用提供服务的方案。
Blazor WebAssembly 托管模型具有以下局限性:
应用仅可使用浏览器功能。 需要可用的客户端硬件和软件(例如 WebAssembly 支持)。 下载项大小较大,应用加载耗时较长。 .NET 运行时和工具支持不够完善。例如,.NET Standard 支持和调试方面存在限制。
项目结构
Blazor 结合了 Razor Page 的开发模式,可以使用 Razor 的语法,文件结构也和 Razor Page 的模式有些类似
Blazor 是以组件为核心的,页面所有的部分都是一个组件
Blazor WebAssembly 对应的 SDK 是 Microsoft.NET.Sdk.BlazorWebAssembly
,来看一下具体的项目文件:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> </PropertyGroup>
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0-preview.4.21253.5" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0-preview.4.21253.5" PrivateAssets="all" /> </ItemGroup>
</Project>
App.razor
: Blazor WebAssembly 应用根组件Program.cs
: 配置应用 WebAssembly host 的入口文件_Imports.razor
: 和 Razor Page 一样,可以在这里定义一些 Razor Page 或者组件里公用的 namespacePages
:包含可以路由到的页面,page 需要使用@page
指令指定Shared
:包含一些公共的组件或者样式定义wwwroot
: 应用公共静态文件的根目录
Routing
在页面组件上通过 @page
指令指定页面路由 @page "/path"
,就会生成一个 RouteAttribute
以支持路由,路由支持像 asp.net core 一样的路由约束和 Path 参数
@page "/RouteParameter/{text}"
<h1>Blazor is @Text!</h1>
@code { [Parameter] public string Text { get; set; }}
@page "/RouteParameter/{text?}"
<h1>Blazor is @Text!</h1>
@code { [Parameter] public string Text { get; set; }
protected override void OnInitialized() { Text = Text ?? "fantastic"; }}
@page "/user/{Id:int}"
<h1>User Id: @Id</h1>
@code { [Parameter] public int Id { get; set; }}
Catch-all
@page "/catch-all/{*pageRoute}"
@code { [Parameter] public string PageRoute { get; set; }}
Interop
Model Binding
最基本的我们需要了解如何做数据绑定,
<div> <input type="checkbox" checked="@item.IsCompleted" /> <h4>@item.TodoTitle</h4> -- <span class="small">@item.CreatedTime.ToStandardTimeString()</span></div><div class="todo-item-details"> <p>@item.TodoContent</p></div>@code{ public List<TodoItem> TodoItems { get; private set; }
protected override async Task OnInitializedAsync() { TodoItems = await scheduler.GetAllTasks(); await base.OnInitializedAsync(); }}
Event Binding
在现在的 Blazor 里,事件绑定是偏向于使用原生的事件名,比如按钮的事件通过 @onclick
方式来绑定事件,例如下面的示例:
<button @onclick="AddNewTodo" class="btn btn-info">Add new todo</button>
为 button 指定了一个 onclick
事件处理器
Call JS method
执行 JS 方法有时候是不可缺少的一部分,因为很多组件都是 JS 的,借助于此,我们就可以直接调用 JS 的方法来实现一些组件功能,示例如下,分是否有返回值可以分为两类:
With return value
@inject IJSRuntime JS@code { private MarkupString text;
private async Task ConvertArray() { text = new(await JS.InvokeAsync<string>("convertArray", quoteArray)); }}
Without return value
@inject IJSRuntime JS@code { private Random r = new(); private string stockSymbol; private decimal price;
private async Task SetStock() { stockSymbol = $"{(char)('A' + r.Next(0, 26))}{(char)('A' + r.Next(0, 26))}"; price = r.Next(1, 101); await JS.InvokeVoidAsync("displayTickerAlert1", stockSymbol, price); }}
More
更多关于 Blazor 相关的知识可以参考微软的文档
References
https://docs.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/dotnet/api/microsoft.jsinterop.ijsruntime?view=dotnet-plat-ext-6.0