关于 blazor
面向 Blazor Server 和 WebAssembly 开发的技能,涵盖组件设计、生命周期、状态、数据绑定与错误处理,也涉及测试、身份验证、API 访问和渲染性能。
主要功能
- 01组件与生命周期指导
- 02状态和数据绑定实践
- 03Server 与 WebAssembly 区别
- 04API 集成与错误处理
- 05测试和身份验证指导
- 06渲染性能优化方法
适用场景
- 01设计可复用的 Blazor 组件
- 02选择 Server 或 WebAssembly
- 03处理 API 数据和界面错误
- 04测试并优化 Blazor 应用
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mindrally/ skills --skill blazor安装后在 Claude Code 中输入/blazor确认已加载。
详细介绍
Blazor 开发指南
你是 Blazor 开发专家,深入了解 Blazor Server 和 Blazor WebAssembly。
组件架构
组件设计
- 创建小巧、专注的组件
- 使用组件参数作为输入
- 使用 EventCallback 处理输出/事件
- 实现 IDisposable 以进行清理
- 谨慎使用级联参数
组件结构
@page "/users/{Id:int}"
@inject IUserService UserService
<h1>@User?.Name</h1>
@code {
[Parameter]
public int Id { get; set; }
private User? User { get; set; }
protected override async Task OnInitializedAsync()
{
User = await UserService.GetUserAsync(Id);
}
}
组件生命周期
生命周期方法
OnInitialized/OnInitializedAsync:初始设置OnParametersSet/OnParametersSetAsync:参数变更时OnAfterRender/OnAfterRenderAsync:DOM 更新后Dispose:清理资源
最佳实践
- 使用
OnInitializedAsync加载数据 - 在
OnAfterRenderAsync中检查firstRender - 释放订阅和计时器
- 避免运行时间过长的同步代码
数据绑定
单向绑定
<p>@message</p>
<input value="@inputValue" />
双向绑定
<input @bind="inputValue" />
<input @bind="inputValue" @bind:event="oninput" />
事件处理
<button @onclick="HandleClick">Click</button>
<button @onclick="() => HandleClickWithParam(id)">Click</button>
<button @onclick="HandleClickAsync">Async Click</button>
渲染优化
避免不必要的渲染
- 对列表项使用
@key - 适当实现
ShouldRender() - 谨慎调用
StateHasChanged() - 避免在循环中使用内联处理程序
虚拟化
<Virtualize Items="@items" Context="item">
<ItemContent>
<div>@item.Name</div>
</ItemContent>
</Virtualize>
状态管理
组件状态
- 使用私有字段保存组件状态
- 外部状态变更时调用
StateHasChanged() - 使用
InvokeAsync进行线程安全的更新
级联参数
<CascadingValue Value="@currentTheme">
<ChildComponent />
</CascadingValue>
[CascadingParameter]
public Theme CurrentTheme { get; set; }
状态容器
- 创建可注入的状态服务
- 使用事件通知状态变更
- 复杂的状态管理可考虑使用 Fluxor
Blazor Server 与 WebAssembly
Blazor Server
- 状态保存在服务器上
- 通过 SignalR 建立实时连接
- 初始加载速度更快
- 需要稳定的连接
- 更适合内部应用
Blazor WebAssembly
- 完全在浏览器中运行
- 初始下载内容较大
- 支持离线运行(具备 PWA 能力)
- 不占用每位用户对应的服务器资源
- 更适合公共应用
API 集成
HTTP 客户端
@inject HttpClient Http
private async Task LoadData()
{
users = await Http.GetFromJsonAsync<List<User>>("api/users");
}
错误处理
try
{
users = await Http.GetFromJsonAsync<List<User>>("api/users");
}
catch (HttpRequestException ex)
{
errorMessage = "Failed to load users";
}
错误处理
错误边界
<ErrorBoundary>
<ChildContent>
<RiskyComponent />
</ChildContent>
<ErrorContent Context="ex">
<p>An error occurred: @ex.Message</p>
</ErrorContent>
</ErrorBoundary>
全局错误处理
- 实现
IErrorBoundary进行自定义处理 - 将错误记录到服务器
- 显示对用户友好的消息
测试
bUnit 测试
[Fact]
public void ComponentRendersCorrectly()
{
using var ctx = new TestContext();
var cut = ctx.RenderComponent<Counter>();
cut.Find("p").MarkupMatches("<p>Current count: 0</p>");
cut.Find("button").Click();
cut.Find("p").MarkupMatches("<p>Current count: 1</p>");
}
身份验证
设置
- 使用
AuthenticationStateProvider - 使用
AuthorizeView控制 UI 的条件显示 - 在页面上使用
[Authorize]特性 - 为 JWT 实现自定义身份验证状态提供程序
AuthorizeView
<AuthorizeView>
<Authorized>
<p>Welcome, @context.User.Identity?.Name!</p>
</Authorized>
<NotAuthorized>
<p>Please log in.</p>
</NotAuthorized>
</AuthorizeView>
性能提示
- 对动态列表使用
@key - 对大型列表实现虚拟化
- 使用
@if延迟加载组件 - 尽量减少 JavaScript 互操作调用
- 在 .NET 8+ 中使用流式渲染
评论
支持 Markdown