Microsoft.FluentUI页面刷新时出现渲染闪烁,如何消除该问题?
问题:Microsoft.FluentUI Blazor 页面刷新时出现无样式闪烁
使用 Microsoft.FluentUI.AspNetCore.Components 开发 Blazor 应用时,刷新页面(F5)会出现明显的无样式闪烁:页面初始渲染时完全未应用任何组件样式,数毫秒后样式才加载生效。该问题可通过官方模板100%复现,操作步骤如下:
dotnet new install Microsoft.FluentUI.AspNetCore.Templates dotnet new fluentblazor --name MyFluentApp cd MyFluentApp dotnet run
启动后访问 /weather 页面,刷新时闪烁现象尤为突出。
解决方案
以下是几种可彻底消除或缓解该闪烁问题的实操方法:
1. 同步加载核心样式文件
将 FluentUI 的核心样式从异步加载改为同步加载,确保样式在页面渲染前完成加载:
- 对于 Blazor Server:修改
_Host.cshtml的<head>区域,替换原有的样式引用:
<!-- 删除原异步加载的 link 标签,替换为同步加载 --> <link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/fluentui.min.css" rel="stylesheet" />
- 对于 Blazor WebAssembly:修改
wwwroot/index.html做同样操作。
2. 启用服务器端预渲染(Blazor Server 专属)
通过服务器端预渲染提前生成带完整样式的页面HTML,客户端拿到的就是已渲染好的页面,避免初始无样式状态:
- 在
Program.cs中配置交互式服务器组件:
builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents();
- 在
_Host.cshtml中设置组件的渲染模式为预渲染:
<component type="typeof(App)" render-mode="ServerPrerendered" />
3. 添加预加载指令提升样式加载优先级
使用 preload 指令告诉浏览器优先加载 FluentUI 样式文件,缩短样式加载时间:
<!-- 放在页面 <head> 的最上方 --> <link rel="preload" href="_content/Microsoft.FluentUI.AspNetCore.Components/css/fluentui.min.css" as="style"> <link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/fluentui.min.css" rel="stylesheet">
4. 用骨架屏掩盖加载过程
如果上述方法仍有轻微闪烁,可添加骨架屏在样式加载完成前占位,降低用户感知:
- 在
App.razor中添加条件渲染逻辑:
@inject IJSRuntime JSRuntime @if (!_stylesLoaded) { <div class="skeleton-wrapper"> <!-- 模拟页面布局的骨架屏,可根据实际页面调整 --> <div class="skeleton-header h-16 bg-gray-200 rounded"></div> <div class="skeleton-content mt-4 space-y-4"> <div class="h-4 bg-gray-200 rounded w-3/4"></div> <div class="h-4 bg-gray-200 rounded w-full"></div> <div class="h-4 bg-gray-200 rounded w-5/6"></div> </div> </div> } else { <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> } @code { private bool _stylesLoaded; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await JSRuntime.InvokeVoidAsync("waitForFluentStyles"); _stylesLoaded = true; StateHasChanged(); } } }
- 在
wwwroot/js/site.js中添加等待样式加载的脚本:
async function waitForFluentStyles() { const styleLink = document.querySelector('link[href*="fluentui.min.css"]'); if (styleLink) { await new Promise(resolve => { if (styleLink.loaded) resolve(); styleLink.onload = resolve; }); } }
内容的提问来源于stack exchange,提问作者maksim
相关产品推荐
相关产品推荐

