Blazor 8中点击修改URL哈希的链接,如何触发NavigationManager.LocationChanged事件?
Blazor 8中触发哈希变化的LocationChanged事件解决方案
在Blazor 8 WebAssembly中,原生<a>标签修改URL哈希时不会触发NavigationManager.LocationChanged事件,这是因为Blazor 8默认的静态渲染模式下,原生链接不会经过Blazor的客户端路由系统。以下是几种可行的解决方法:
方法1:使用Blazor的NavigateTo替代原生链接
将原生<a>标签替换为Blazor的交互式导航,通过NavigationManager.NavigateTo方法修改哈希,这样会触发LocationChanged事件:
@page "/" @rendermode InteractiveWebAssembly @inject NavigationManager _navigationManager @implements IDisposable <h1>Hello, world!</h1> <button @onclick="() => _navigationManager.NavigateTo("#login", forceLoad: false)">Login</button> | <button @onclick="() => _navigationManager.NavigateTo("#signup", forceLoad: false)">Sign Up</button> | <button @onclick="() => _navigationManager.NavigateTo("#forgotpassword", forceLoad: false)">Forgot Password</button> @code { protected override void OnInitialized() { _navigationManager.LocationChanged += _navigationManager_LocationChanged; base.OnInitialized(); } void _navigationManager_LocationChanged(object sender, LocationChangedEventArgs e) { Console.WriteLine("_navigationManager_LocationChanged: " + e.Location); } void IDisposable.Dispose() { _navigationManager.LocationChanged -= _navigationManager_LocationChanged; } }
方法2:保留原生链接,监听浏览器hashchange事件
如果需要保留原生<a>标签,可以通过JS互操作监听浏览器的hashchange事件,再同步到Blazor中:
组件代码
@page "/" @rendermode InteractiveWebAssembly @inject NavigationManager _navigationManager @inject IJSRuntime _jsRuntime @implements IDisposable <h1>Hello, world!</h1> <a href="#login">Login</a> | <a href="#signup"> Sign Up</a> | <a href="#forgotpassword">Forgot Password</a> @code { private DotNetObjectReference<Index>? _dotNetRef; protected override async Task OnInitializedAsync() { _navigationManager.LocationChanged += _navigationManager_LocationChanged; _dotNetRef = DotNetObjectReference.Create(this); await _jsRuntime.InvokeVoidAsync("setupHashChangeListener", _dotNetRef); await base.OnInitializedAsync(); } [JSInvokable] public void OnHashChanged(string newUrl) { // 同步哈希变化到NavigationManager,触发LocationChanged _navigationManager.NavigateTo(newUrl, forceLoad: false, replace: true); } void _navigationManager_LocationChanged(object sender, LocationChangedEventArgs e) { Console.WriteLine("_navigationManager_LocationChanged: " + e.Location); } void IDisposable.Dispose() { _navigationManager.LocationChanged -= _navigationManager_LocationChanged; _dotNetRef?.Dispose(); _jsRuntime.InvokeVoidAsync("removeHashChangeListener"); } }
新增JS代码(在wwwroot/index.html中)
<script> let hashChangeListener; function setupHashChangeListener(dotNetRef) { hashChangeListener = () => { dotNetRef.invokeMethodAsync('OnHashChanged', window.location.href); }; window.addEventListener('hashchange', hashChangeListener); } function removeHashChangeListener() { if (hashChangeListener) { window.removeEventListener('hashchange', hashChangeListener); } } </script>
关键注意事项
- 确保组件使用交互式渲染模式:添加
@rendermode InteractiveWebAssembly,静态渲染模式下不会处理客户端路由事件。 - 使用
NavigateTo时,forceLoad: false确保不会重载页面,仅修改客户端路由。
内容的提问来源于stack exchange,提问作者Arvin
相关产品推荐
相关产品推荐

