.NET 8无预渲染场景下,如何在加载WASM组件时显示加载进度?
.NET 8 Blazor跨渲染模式页面切换的加载提示解决方案
针对从非WASM页面(如/home)切换到无预渲染的InteractiveWebAssemblyRenderMode页面(如/wasmPage)时,Blazor清空<main>后无加载提示的问题,以下是几个无需复杂修改的可行方案:
方案一:DOM突变观察器+CSS/JS(最简洁)
通过监听<main>元素的DOM变化,检测bl-load注释的出现/消失来控制加载提示的显示:
- 添加加载提示元素
在主布局(如MainLayout.razor)中插入全局加载提示:
<div class="wasm-loader"> <p>正在加载WASM内容...</p> </div>
- 基础CSS样式
设置提示的固定定位和默认隐藏状态:
.wasm-loader { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.9); display: none; align-items: center; justify-content: center; z-index: 9999; font-size: 1.2rem; }
- DOM监听JS脚本
在wwwroot/js/loader.js中添加突变观察器:
document.addEventListener('DOMContentLoaded', () => { const main = document.querySelector('main'); const loader = document.querySelector('.wasm-loader'); const observer = new MutationObserver(mutations => { // 检查main中是否存在bl-load注释 const hasBlLoad = Array.from(main.childNodes).some(node => node.nodeType === Node.COMMENT_NODE && node.textContent.includes('bl-load') ); loader.style.display = hasBlLoad ? 'flex' : 'none'; }); // 监听main的子节点变化 observer.observe(main, { childList: true }); });
最后在index.html中引入该脚本:
<script src="js/loader.js"></script>
方案二:导航事件+JS互操作
通过订阅导航事件,判断目标页面类型,主动控制加载提示:
布局中添加加载元素
同方案一的加载提示元素。订阅导航事件
在MainLayout.razor中注入NavigationManager和IJSRuntime,并在初始化时订阅位置变化事件:
@inject NavigationManager NavManager @inject IJSRuntime JSRuntime <!-- 加载提示元素 --> <div id="wasm-loader" class="wasm-loader"> <p>正在加载WASM内容...</p> </div> @code { protected override void OnInitialized() { NavManager.LocationChanged += async (_, args) => { // 根据路由判断是否为WASM页面(可根据实际路由规则调整) if (args.Location.Contains("/wasmPage")) { await JSRuntime.InvokeVoidAsync("showLoader"); // 监听WASM加载完成事件 await JSRuntime.InvokeVoidAsync("onWasmLoaded", () => HideLoader()); } }; } private async Task HideLoader() { await JSRuntime.InvokeVoidAsync("hideLoader"); } }
- 添加JS函数
在wwwroot/js/interop.js中实现显示/隐藏逻辑:
function showLoader() { document.getElementById('wasm-loader').style.display = 'flex'; } function hideLoader() { document.getElementById('wasm-loader').style.display = 'none'; } function onWasmLoaded(callback) { // 监听Blazor WASM就绪事件 if (window.Blazor?.webassemblyReady) { callback(); } else { window.addEventListener('blazorWebAssemblyReady', callback); } }
方案三:自定义RouteView拦截渲染
通过继承RouteView,在渲染WASM页面之前显示加载提示:
- 创建自定义RouteView
新建CustomRouteView.razor:
@inherits RouteView @inject IJSRuntime JSRuntime @if (_showLoading) { <div class="wasm-loader"> <p>正在加载WASM内容...</p> </div> } else { <LayoutView Layout="@Layout"> <RouteData RouteData="@RouteData" /> </LayoutView> } @code { private bool _showLoading; protected override async Task OnParametersSetAsync() { // 检查当前页面是否使用无预渲染的WASM渲染模式 var renderAttr = RouteData.PageType.GetCustomAttributes(typeof(RenderModeAttribute), false) .Cast<RenderModeAttribute>() .FirstOrDefault(); if (renderAttr?.RenderMode is InteractiveWebAssemblyRenderMode mode && !mode.Prerender) { _showLoading = true; // 等待WASM加载完成后更新状态 await JSRuntime.InvokeVoidAsync("onWasmLoaded", () => { _showLoading = false; StateHasChanged(); }); } else { _showLoading = false; await base.OnParametersSetAsync(); } } }
- 替换App.razor中的RouteView
修改App.razor,使用自定义的CustomRouteView:
<Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <CustomRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>抱歉,该页面不存在。</p> </LayoutView> </NotFound> </Router>
- 引入JS函数
同方案二中的onWasmLoaded等JS函数。
内容的提问来源于stack exchange,提问作者Alamakanambra
相关产品推荐
相关产品推荐

