目录
[为什么你的 Blazor 代码即将变得更简单](#为什么你的 Blazor 代码即将变得更简单)
[.NET 10:"我们真正修复了状态"版本](#.NET 10:“我们真正修复了状态”版本)
[电路状态持久性("我的 WebSocket 连接断开"问题)](#电路状态持久性(“我的 WebSocket 连接断开”问题))
[性能:Blazor .NET 10 基准测试](#性能:Blazor .NET 10 基准测试)
[Blazor .NET 10 中的 JavaScript 互操作](#Blazor .NET 10 中的 JavaScript 互操作)
[404 处理方式合情合理](#404 处理方式合情合理)
[QuickGrid 更新](#QuickGrid 更新)
[1. 过度使用[PersistentState]](#1. 过度使用[PersistentState])
[2. 忘记新的验证注册](#2. 忘记新的验证注册)
[3. 假设通行密钥在所有地方都有效](#3. 假设通行密钥在所有地方都有效)
[4. 忽略电路暂停/恢复](#4. 忽略电路暂停/恢复)
[.NET 10 是 LTS 版本吗?](#.NET 10 是 LTS 版本吗?)
[Blazor .NET 10 的最大改进是什么?](#Blazor .NET 10 的最大改进是什么?)
[Blazor .NET 10 是否支持密码?](#Blazor .NET 10 是否支持密码?)
[.NET 10 中的 Blazor JavaScript 包体积缩小了多少?](#.NET 10 中的 Blazor JavaScript 包体积缩小了多少?)
[我可以在 .NET 10 中使用 Blazor WebAssembly 的热重载功能吗?](#我可以在 .NET 10 中使用 Blazor WebAssembly 的热重载功能吗?)
[如何从 .NET 9 迁移到 .NET 10?](#如何从 .NET 9 迁移到 .NET 10?)

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。
探索 Blazor .NET 10 的所有新特性:持久状态管理、改进的 JavaScript 互操作性、密钥身份验证以及显著的性能提升。这是一份面向 .NET 开发人员的全面指南,其中包含代码示例。
为什么你的 Blazor 代码即将变得更简单
Blazor 在 .NET 10 中的出现,标志着微软 Web UI 框架向前迈出了重要一步。我还记得 Blazor 曾经是 .NET 圈子里一个特立独行的孩子。"你想在浏览器里运行 C#?这太可爱了。" 快进到 2025 年,Blazor .NET 10 不再是弱者,而是真正的竞争者。
Blazor 一直都很好用。但有些图案需要比实际需要的更繁琐的步骤。
.NET 10 最终解决了之前存在的一些问题。有关官方概述,请参阅微软的ASP.NET Core 10.0 新特性文档。

样板问题
很多开发者都经历过这种情况:你启动了一个 Blazor 项目,兴致勃勃,编写组件,组件运行正常,一切顺利。
然后你的老板问:"为什么页面在导航时会闪白光?"
然后你发现了预渲染、水合以及双重渲染问题。框架处理了所有这些,但你必须自己编写底层逻辑。手动序列化状态、权衡OnInitializedAsync各种方案OnAfterRenderAsync、构建那些感觉本应内置的抽象层。
六个月后,你的Program.cs:
builder.Services.AddScoped<IStateContainer, StateContainer>();
builder.Services.AddScoped<IPreRenderStateService, PreRenderStateService>();
builder.Services.AddScoped<IHydrationHelper, HydrationHelper>();
builder.Services.AddScoped<IComponentStateManager, ComponentStateManager>();
builder.Services.AddScoped<ICircuitHandler, CustomCircuitHandler>();
builder.Services.AddSingleton<IReconnectionStateTracker, ReconnectionStateTracker>();
// Services that worked great, but shouldn't have been your job to write
获取天气数据的组件?它获取了两次。一次是在预渲染阶段,一次是在交互模式下。你的 API 团队肯定恨死你了。
.NET 10:"我们真正修复了状态"版本
让我来向您展示一下新增功能,以及它为何如此重要。
持久状态,不会让你哭泣
.NET 10 之前:
@inject PersistentComponentState ApplicationState
@code {
private WeatherForecast[]? forecasts;
private PersistingComponentStateSubscription _subscription;
protected override async Task OnInitializedAsync()
{
_subscription = ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>("forecasts", out forecasts))
{
forecasts = await FetchForecasts();
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("forecasts", forecasts);
return Task.CompletedTask;
}
public void Dispose()
{
_subscription.Dispose();
}
}
仅仅为了避免重复获取数据,就需要 25 行繁琐的代码。每个组件都是如此。
.NET 10 之后:
@code {
PersistentState
public WeatherForecast[]? Forecasts { get; set; }
protected override async Task OnInitializedAsync()
{
Forecasts ??= await FetchForecasts();
}
}
一个属性。就这么简单。运行时会处理序列化、数据填充和清理。你的 API 团队甚至可能再次邀请你共进午餐。在官方文档中了解更多关于Blazor 状态管理的信息。

电路状态持久性("我的 WebSocket 连接断开"问题)
你肯定遇到过这种情况:用户填写了一份复杂的表格,然后网络出现故障,WebSocket 连接断开,Blazor 服务器重新连接。
他们的所有数据?都没了。他们得重新开始。他们会放弃你的应用。他们会写差评。
.NET 10 修复了这个问题:
// When the user goes idle or connection is unstable
Blazor.pause();
// Later, when they're back
await Blazor.resume();
在连接断开之前调用时Blazor.pause(),.NET 10 会将电路状态持久化到浏览器存储中。即使服务器上的原始电路已被清除,您也可以稍后恢复连接。实际上,这种持久性取决于您的服务器设置和浏览器的存储生命周期。请将其理解为"更具弹性",而不是"无限会话永存"。
这使得 Blazor Server 在高要求的企业级应用场景中更具弹性。更多详情,请参阅 Microsoft 的Blazor Server 重新连接文档。
性能:Blazor .NET 10 基准测试
以下是一个典型的 Blazor Web 应用的修改前后对比图(具体数值会根据配置和应用结构而有所不同):
| 资产 | .NET 9 | .NET 10 | 改进 |
|---|---|---|---|
blazor.web.js |
约183 KB | 约43 KB | 缩小约 76% |
| 启动清单 | 单独的文件 | 内联dotnet.js |
请求减少 1 次 |
| 资产交付 | 嵌入式资源 | 静态指纹识别 | 更好的缓存 |
那个 JavaScript 包?它已经大幅精简了。你的 Lighthouse 分数会感谢你的。
等等,还有更多惊喜。.NET 10 会在 Blazor Web 应用中通过 Link 标头自动预加载 Blazor 框架资源,并在独立 WebAssembly 中启用高优先级下载。运行时会在页面渲染时下载资源,而不是渲染后再下载。
首次渲染完成,用户可以看到内容。与此同时,Blazor 运行时在后台下载。无需任何特殊组件------框架会自动处理。
这就像"这个应用运行缓慢"和"这个应用运行瞬间完成"之间的区别。

Blazor .NET 10 中的 JavaScript 互操作
旧版 JS 的互操作性是......函数式的。你可以调用函数,可以传递基本类型,但你只能祈祷 JSON 序列化不会崩溃。
.NET 10 增加了实际的对象语义:
// Create a JS object instance
var chart = await JS.InvokeConstructorAsync<IJSObjectReference>(
"Chart",
canvasElement,
chartConfig
);
// Read properties
var currentValue = await chart.GetValueAsync<int>("currentValue");
// Set properties
await chart.SetValueAsync("animationDuration", 500);
// For performance-critical code (in-process only)
var syncValue = chart.GetValue<int>("dataLength");
现在你操作的是实际对象,不再只是字符串和祈祷文了。对于嵌套很深的属性路径,通常仍然需要编写一个简单的 JavaScript 辅助函数,并从 .NET 中调用它。完整的 API 参考请参见"从 .NET 调用 JavaScript" 。
真正的胜利:制造商的支持
以前,创建JS对象看起来像这样:
await JS.InvokeVoidAsync("eval", "window.myChart = new Chart(canvas, config)");
var reference = await JS.InvokeAsync<IJSObjectReference>("eval", "window.myChart");
评估。在生产代码中。我见过。我也写过。我们都见过。
现在:
var myChart = await JS.InvokeConstructorAsync<IJSObjectReference>("Chart", canvas, config);
无需评估,不会造成全球污染,只有纯净的互操作性。

WebAssembly热重载
Blazor 的热重载功能一直褒贬不一。服务器端表现相当不错。WebAssembly 端呢?需要手动配置,而且有时根本就没法配置。
.NET 10 迁移到了 WebAssembly 的通用热重载实现。SDK 现在会自动处理它。
<!-- This is now true by default for Debug builds -->
<PropertyGroup>
<WasmEnableHotReload>true</WasmEnableHotReload>
</PropertyGroup>
您无需添加此功能,它已启用。编辑.razor文件并保存,即可立即查看更改。无需重新构建,无需刷新浏览器,也无需任何配置。
对于具有自定义构建配置的团队:
<!-- Enable for non-Debug configurations -->
<PropertyGroup Condition="'$(Configuration)' == 'Staging'">
<WasmEnableHotReload>true</WasmEnableHotReload>
</PropertyGroup>
工作流程终于达到了应有的水平:编辑代码、保存、查看更改。Blazor WASM 的内部开发循环现在几乎可以与 JavaScript 框架多年来一直拥有的流程相媲美。

表单验证源生成器
这一点虽然细微,但却很重要。
**.NET 10 之前:**验证使用反射。每次表单提交时,运行时都会遍历模型,查找属性并构建验证器。虽然可行,但对 AOT 不友好,而且速度也不快。
.NET 10 之后:
// Program.cs
builder.Services.AddValidation();
// Your model
ValidatableType\] // New: enables source-generated validators in .NET 10 public class OrderForm { \[Required
public string CustomerName { get; set; }
Range(1, 100)
public int Quantity { get; set; }
ValidateComplexType\] // Now works with the source generator for nested objects
public Address ShippingAddress { get; set; }
\[ValidateEnumeratedItems\] // Collection items validated via the generator
public List\
public DateTime LastClick { get; set; } // Why are you persisting this?
PersistentState
public bool IsMenuOpen { get; set; } // UI state doesn't need persistence
持久化数据,而非用户界面状态。序列化开销并非没有。
2. 忘记新的验证注册
// This won't work with [ValidatableType]
builder.Services.AddRazorComponents();
// You need this too
builder.Services.AddValidation();
源生成器创建验证器AddValidation()并注册它们。
3. 假设通行密钥在所有地方都有效
// Check for support first
if (await PasskeyService.IsSupported())
{
// Show passkey options
}
else
{
// Fallback to password
}
老款 iOS 系统上的 Safari 浏览器?某些安卓浏览器?策略奇葩的企业网络?密码支持情况不一。务必准备备用方案。
4. 忽略电路暂停/恢复
// The connection died, but you didn't pause first
// State is lost. User is sad.
// Do this instead
window.addEventListener('beforeunload', () => {
Blazor.pause();
});
只有当你明确告诉 Blazor 持久化电路状态时,电路状态持久化才会生效。
何时升级
| 情况 | 推荐 |
|---|---|
| 新项目 | 当然要从.NET 10开始。 |
| .NET 9,太棒了! | 如果您对升级比较谨慎,可以考虑等待第一个 .NET 10 服务更新。 |
| .NET 9 遇到状态问题 | 现在就升级吧,[PersistentState]光这一点就值回票价。 |
| .NET 8 LTS | 你可以在2026年11月之前完成迁移。但第10年也是长期支持计划(LTS)。做好迁移计划吧。 |
| .NET 6 或更早版本 | 你在干什么?昨天就升级了。 |
.NET 10 是一个长期支持 (LTS) 版本,提供三年支持。它是生产应用程序的理想选择。
常见问题解答
.NET 10 是 LTS 版本吗?
是的,.NET 10 是一个长期支持 (LTS) 版本,微软提供三年的支持。这使其成为需要稳定性和长期维护的生产应用程序的理想选择。之前的 LTS 版本是 .NET 6 和 .NET 8。
Blazor .NET 10 的最大改进是什么?
可以说,这个[PersistentState]属性的加入是影响最大的改动。它将 25 行以上的手动状态序列化代码简化为一个属性,从而消除了预渲染和水合期间的重复渲染问题和冗余 API 调用。
Blazor .NET 10 是否支持密码?
是的,ASP.NET Core Identity 现在内置了对 WebAuthn/FIDO2 密钥身份验证的支持。这使得指纹登录、面容 ID 和硬件安全密钥无需第三方库即可使用。Blazor Web 应用模板会自动生成必要的端点和 UI 组件。
.NET 10 中的 Blazor JavaScript 包体积缩小了多少?
.NET 10 中,该blazor.web.js软件包的大小从 .NET 9 的约 183 KB 减少到约 43 KB,体积缩小了约 76%。此外,启动清单现在已内联,从而在启动过程中减少了一次额外的 HTTP 请求。
我可以在 .NET 10 中使用 Blazor WebAssembly 的热重载功能吗?
是的,Blazor WebAssembly Debug 版本现在默认启用热重载。编辑文件.razor并保存后,无需重新构建或刷新浏览器即可立即看到更改。对于非 Debug 配置(例如 Staging),您可以使用以下命令手动启用它<WasmEnableHotReload>true</WasmEnableHotReload>:
如何从 .NET 9 迁移到 .NET 10?
更新目标框架名称 (TFM) net10.0,builder.Services.AddValidation()如果使用新的源生成验证器,请添加相关配置,查看新的重新连接 UI 组件,并测试导航行为的更改。考虑使用[PersistentState]属性替换手动状态持久化。有关详细信息,请参阅迁移清单部分。
最后想说的话
每次 Blazor 版本发布,我都会寻找能够让开发体验更流畅、减少缺陷的改进之处。
.NET 10 表现出色。
Blazor 已经成熟,可以投入生产环境多年------许多企业自 2019 年以来就一直在成功运行它。但 .NET 10 更进一步。状态管理不再仅仅是函数式的,而是更加优雅。性能卓越。JavaScript 互操作性也更加现代化。开发者体验显著提升。
它完美吗?不。调试机制仍需改进。组件库生态系统仍然比 React 小。WASM 中的一些极端情况仍然需要变通方法。
但 .NET 10 消除了我过去在推荐 Blazor 时提到的许多注意事项。它不仅是 .NET 团队的可靠选择,而且完全可以与任何现代 Web 框架相媲美。
.NET 10 提高了标准。
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。