Blazor 页面导航后自动滚动到顶部,核心是监听路由变化并在新页面加载完成时触发
window.scrollTo(0, 0)。不同 Blazor 模式(WASM / Server)实现略有差异,但思路一致:利用框架提供的导航生命周期钩子或 JS 互操作。
使用 NavigationManager.LocationChanged 事件(推荐)
这是最通用、无需 JS 互操作的方式,适用于 Blazor WASM 和 Blazor Server。
在 _Host.cshtml(Server)或 Program.cs(WASM)中注册全局监听器,或在根组件(如MainLayout.razor)中处理 注意:该事件在导航开始时触发,但 DOM 渲染可能尚未完成,所以需延迟执行滚动(例如用
await Task.Delay(1)或
JSRuntime.InvokeVoidAsync("setTimeout", ...))
示例(放在 MainLayout.razor中):
@inject NavigationManager Navigation
@inject IJSRuntime JSRuntime
<p>@code {
protected override void OnInitialized()
{
Navigation.LocationChanged += OnLocationChanged;
}</p><pre class="brush:php;toolbar:false;">private async void OnLocationChanged(object? sender, LocationChangedEventArgs args)
{
// 等待渲染队列清空,确保新页面 DOM 已就绪
await Task.Delay(1);
await JSRuntime.InvokeVoidAsync("scrollTo", 0, 0);
}
public void Dispose()
{
Navigation.LocationChanged -= OnLocationChanged;
}}
在页面组件中使用 OnAfterRenderAsync(按需补充)
适合需要更精细控制的场景,比如仅对某些页面启用、或配合加载状态判断。
在目标页面组件中重写OnAfterRenderAsync,结合一个布尔标记(如
shouldScrollToTop)控制只执行一次 首次渲染后滚动,然后重置标记 注意避免无限循环:仅在
firstRender == true且标记为真时滚动
纯 JavaScript 方案(备用)
如果 C# 层时机难以把握,可直接在 JS 中监听
hashchange或
popstate,或利用 Blazor 的
afterNavigate全局事件(Blazor 6.0+)。 在
wwwroot/index.html(WASM)或
_Host.cshtml(Server)的
<script></script>中添加:
window.addEventListener('beforeunload', () => {
// 可选:记录离开前位置,用于返回时恢复
});
<p>// Blazor 6.0+ 提供的导航完成事件
window.addEventListener('afterNavigate', () => {
window.scrollTo(0, 0);
});</p>基本上就这些。优先用
NavigationManager.LocationChanged + Task.Delay(1)组合,稳定、简洁、不依赖额外 JS。注意清理事件订阅防止内存泄漏,尤其在布局组件中实现时。
