目录
1. 简介
Blazor 是 Microsoft 推出的开源框架,用于使用 C# 和 .NET 构建交互式 Web 应用程序,减少对 JavaScript 的依赖。
核心特性
-
• 使用 C# 编写前端和后端逻辑,统一开发体验。
-
• 组件化开发,支持代码复用。
-
• 支持两种托管模型:Blazor Server 和 Blazor WebAssembly。
-
• 与 ASP.NET Core 深度集成,支持 SignalR、依赖注入等。
-
• 支持 AOT(Ahead-of-Time)编译以提升 WebAssembly 性能。
最新动态(截至 2025 年)
-
• Blazor 在 .NET 8 和 .NET 9 中持续优化,支持混合模式(Blazor Hybrid)用于桌面和移动端开发(如 MAUI)。
-
• 新增特性:增强的 SSR(服务器端渲染)支持、改进的组件生命周期管理。
2. 托管模型
| 特性 | Blazor Server | Blazor WebAssembly |
| 首次加载速度 | 快 | 慢(需下载运行时) |
| 是否依赖网络 | 是 | 否 |
| 适用场景 | 内部系统、实时协作 | 单页应用、离线应用 |
Blazor Server
-
• 运行方式:应用程序在服务器上运行,通过 SignalR 实时更新客户端 UI。
-
• 优点:
-
• 初始加载快
-
• 可直接访问数据库、文件系统
-
• 兼容性好
-
-
• 缺点:
-
• 依赖网络连接
-
• 服务器负载较高
-
-
• 适用场景:企业内部系统、聊天、仪表板。
Blazor WebAssembly
-
• 运行方式:应用程序编译为 WebAssembly,在客户端浏览器运行。
-
• 优点:
-
• 完全在客户端运行,支持离线
-
• 部署简单,适合 CDN
-
• 借助 AOT 编译,性能接近原生
-
-
• 缺点:
-
• 首次加载较慢(约 2-5MB)
-
• 浏览器需支持 WebAssembly
-
-
• 适用场景:SPA、跨平台 Web 应用、离线应用。
Blazor Hybrid
-
• 运行方式:结合 Blazor 和 .NET MAUI,用于开发桌面和移动端应用。
-
• 特点:本地运行,复用 Blazor 组件,适合跨平台开发。
-
• 适用场景:需要原生体验的应用。
3. 项目结构
-
•
Pages文件夹:页面组件(.razor),通过@page定义路由。 -
•
Components文件夹:可复用组件。 -
•
wwwroot文件夹:静态资源(CSS、JS、图片等)。 -
•
Program.cs:入口点,配置服务。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents(); // 注册 Blazor 组件服务
var app = builder.Build();
app.UseRouting();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode(); // 渲染模式
app.Run();
-
•
App.razor:根组件,管理路由。
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="typeof(MainLayout)" />
</Found>
<NotFound>
<p>Sorry, page not found!</p>
</NotFound>
</Router>
-
•
MainLayout.razor:定义布局。 -
•
Shared文件夹:共享组件(如导航栏)。
4. 组件开发
基本结构
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
StateHasChanged(); // 手动刷新 UI
}
}
关键点
-
•
@page定义路由。 -
•
@code包含 C# 逻辑。 -
•
@用于绑定数据或事件。
5. 数据绑定
单向绑定
<p>Message: @message</p>
@code {
private string message = "Hello, Blazor!";
}
双向绑定
<input @bind="inputValue" />
<p>You typed: @inputValue</p>
@code {
private string inputValue = "";
}
表单验证
<EditForm Model="@user" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<InputText @bind-Value="user.Name" />
<ValidationMessage For="@(() => user.Name)" />
<button type="submit">Submit</button>
</EditForm>
@code {
private User user = new();
private void HandleValidSubmit() => Console.WriteLine($"Submitted: {user.Name}");
public class User {
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
}
}
6. 路由
@page "/user/{Id:int}"
<p>User ID: @Id</p>
@code {
[Parameter]
public int Id { get; set; }
}
导航
@inject NavigationManager Navigation
<button @onclick="NavigateToAbout">Go to About</button>
@code {
private void NavigateToAbout() => Navigation.NavigateTo("/about?query=example");
}
路由约束
@page "/product/{ProductId:guid}"
7. 依赖注入
@inject HttpClient Http
@inject IJSRuntime JS
@inject NavigationManager Navigation
@code {
protected override async Task OnInitializedAsync() {
var data = await Http.GetStringAsync("https://api.example.com/data");
}
}
自定义服务
-
1. 定义接口和服务:
public interface IMyService {
string GetData();
}
public class MyService : IMyService {
public string GetData() => "Hello from service!";
}
-
2. 注册服务(
Program.cs):
builder.Services.AddSingleton<IMyService, MyService>();
-
3. 使用服务:
@inject IMyService MyService
<p>@MyService.GetData()</p>
8. 生命周期方法
@code {
protected override async Task OnInitializedAsync() {
// 初始化数据
}
protected override void OnParametersSet() {
// 参数变化时执行
}
protected override void OnAfterRender(bool firstRender) {
if (firstRender) {
// 首次渲染后操作
}
}
protected override bool ShouldRender() {
return isDataChanged;
}
}
9. 调用 JavaScript
C# 调用 JS
@inject IJSRuntime JS
<button @onclick="ShowAlert">Show Alert</button>
@code {
private async Task ShowAlert() => await JS.InvokeVoidAsync("alert", "Hello from Blazor!");
}
JS 调用 C#
[JSInvokable]
public static Task<string> GetMessage() => Task.FromResult("Hello from C#!");
async function callDotNet() {
const result = await DotNet.invokeMethodAsync('MyAssembly', 'GetMessage');
console.log(result);
}
10. 状态管理
public class AppState {
public int Counter { get; set; }
public event Action OnChange;
public void IncrementCounter() {
Counter++;
OnChange?.Invoke();
}
}
注册服务并使用:
builder.Services.AddSingleton<AppState>();
@inject AppState State
<p>Counter: @State.Counter</p>
@code {
protected override void OnInitialized() {
State.OnChange += StateHasChanged;
}
}
11. CSS 和样式
隔离 CSS
/* MyComponent.razor.css */
h3 {
color: blue;
}
全局 CSS
<link href="css/site.css" rel="stylesheet" />
内联样式
<div style="color: red;">Red text</div>
12. 性能优化
-
• 使用
ShouldRender控制是否重新渲染。 -
• 避免在循环中创建大量组件实例。
-
• 懒加载组件:
@if (isLoaded) {
<HeavyComponent />
}
-
• AOT 编译(WebAssembly):
<PropertyGroup>
<RunAotCompilation>true</RunAotCompilation>
</PropertyGroup>
Blazor 新特性(.NET 8/9)
-
• 静态服务器端渲染 (SSR):
<Routes @rendermode="RenderMode.Static" />
-
• 新增 InputFile 组件:
<InputFile OnChange="@HandleFileUpload" />
@code {
private async Task HandleFileUpload(InputFileChangeEventArgs e) {
var file = e.File;
// 处理文件
}
}
-
• 流式渲染:逐步加载页面内容,提升用户体验。

261

被折叠的 条评论
为什么被折叠?



