Blazor Server+Bootstrap侧滑导航双击打开问题及解决困境
Blazor Server + Bootstrap Offcanvas 双击触发及后续问题解决
原问题:路由跳转后侧滑导航需双击打开
本质是Blazor Server静态渲染模式下,Bootstrap的Offcanvas JS初始化逻辑在路由跳转后没有重新绑定。首次点击时,Bootstrap仅完成了状态类的标记,但没触发弹窗的显示逻辑,第二次点击才会执行完整的打开流程。
你用@rendermode Interactive Server解决了双击问题,但引出两个新问题,下面是针对性的解决方法:
问题1:页面跳转后菜单不自动关闭
通过注入NavigationManager监听路由变化,手动关闭Offcanvas:
@inject NavigationManager NavManager @implements IDisposable <!-- 保留你的Offcanvas按钮和容器代码 --> <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNav" aria-controls="offcanvasNav"> <i class="bi bi-list"></i> </button> <div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasNav" aria-labelledby="offcanvasNavLabel" @ref="_offcanvas"> <!-- Offcanvas内容不变 --> </div> @code { private Offcanvas? _offcanvas; protected override void OnInitialized() { NavManager.LocationChanged += OnRouteChanged; } private async void OnRouteChanged(object? sender, LocationChangedEventArgs e) { if (_offcanvas?.IsShown == true) { await _offcanvas.HideAsync(); } } public void Dispose() { NavManager.LocationChanged -= OnRouteChanged; } }
问题2:自定义激活链接功能失效
原代码里的路径判断只会在组件初始化时执行一次,路由变化后不会自动更新。需要监听路由变化事件,刷新当前路径并触发组件重渲染:
@inject NavigationManager NavManager @implements IDisposable <li class="admin-dropdown"> <a class="admin-item dropdown-item @(IsActiveRoute("/Admin/Courses"))" href="/Admin/Courses"> Edit Courses <i class="bi bi-chevron-right"></i> </a> </li> @code { private string _currentPath = string.Empty; protected override void OnInitialized() { _currentPath = GetCurrentRelativePath(); NavManager.LocationChanged += OnRouteChanged; } private string GetCurrentRelativePath() { return new Uri(NavManager.Uri).AbsolutePath; } private bool IsActiveRoute(string route) { return _currentPath.Equals(route, StringComparison.OrdinalIgnoreCase); } private void OnRouteChanged(object? sender, LocationChangedEventArgs e) { _currentPath = GetCurrentRelativePath(); StateHasChanged(); // 更新激活状态 } public void Dispose() { NavManager.LocationChanged -= OnRouteChanged; } }
替代方案:不启用Interactive Server解决双击问题
如果想保持静态渲染模式,也可以在组件渲染完成后手动初始化Bootstrap Offcanvas:
@inject IJSRuntime JSRuntime @inject NavigationManager NavManager @implements IDisposable <!-- 你的Offcanvas代码 --> @code { protected override async Task OnAfterRenderAsync(bool firstRender) { await ReInitOffcanvas(); if (firstRender) { NavManager.LocationChanged += async (s, e) => await ReInitOffcanvas(); } } private async Task ReInitOffcanvas() { // 先销毁已有的实例,再重新初始化 await JSRuntime.InvokeVoidAsync("(() => { const offcanvas = bootstrap.Offcanvas.getInstance('#offcanvasNav'); if(offcanvas) offcanvas.dispose(); new bootstrap.Offcanvas('#offcanvasNav'); })"); } public void Dispose() { NavManager.LocationChanged -= async (s, e) => await ReInitOffcanvas(); } }
这种方式无需启用Interactive Server,直接通过JS重新初始化解决双击问题,也不会带来后续的菜单关闭和激活链接问题。
内容的提问来源于stack exchange,提问作者Miriah Smith
相关产品推荐
相关产品推荐

