如何通过JavaScript和Blazor以编程方式关闭Bootstrap Offcanvas组件?
Blazor .NET 8 + Bootstrap 5.3 Offcanvas 点击菜单项后无法关闭问题修复
问题原因
你当前的JS代码每次调用closeOffcanvas时都会新建一个bootstrap.Offcanvas实例,但Bootstrap会自动跟踪已初始化的组件实例。重复创建实例会导致多个实例同时控制同一个Offcanvas元素,引发状态冲突:既无法正确触发关闭逻辑,还会干扰默认关闭按钮的事件绑定,导致按钮失效。
解决方案1:复用Bootstrap已有的Offcanvas实例
修改closeOffcanvas.js,使用Bootstrap官方提供的实例获取方法,避免重复创建实例:
window.closeOffcanvas = function () { const offcanvasElement = document.getElementById("offcanvasid"); // 获取已初始化的实例,确保状态统一 const offcanvasInstance = bootstrap.Offcanvas.getInstance(offcanvasElement); if (offcanvasInstance) { offcanvasInstance.hide(); } };
更简洁的写法(自动处理实例存在性):
window.closeOffcanvas = function () { bootstrap.Offcanvas.getOrCreateInstance(document.getElementById("offcanvasid")).hide(); };
解决方案2:纯Blazor方式控制Offcanvas(无需JS)
如果想完全贴合Blazor的状态驱动模式,避免JS交互,可以直接通过绑定布尔值控制Offcanvas显示:
修改Filter.razor的HTML部分
<button class="btn btn-primary btn-sm" @onclick="ToggleOffcanvas"> Contents <i class="fas fa-bars"></i> </button> <!-- 通过绑定Bootstrap的show类控制显示状态 --> <div class="offcanvas offcanvas-end @(_isOffcanvasOpen ? "show" : "")" tabindex="-1" id="offcanvasid" aria-modal="@_isOffcanvasOpen"> <div class="offcanvas-header"> <span></span> <button type="button" class="btn-close" @onclick="ToggleOffcanvas" aria-label="Close"></button> </div> <div class="offcanvas-body"> <ul class="list-group"> @foreach (var item in Enums.MenuItem.List.OrderBy(o => o.Value)) { <li class="list-group-item @ActiveFilter(item)"> <a @onclick="@(e => ButtonClicked(item))" type="button" id="@item.ButtonId"> @item.Value <small>@item.Title</small> </a> </li> } </ul> </div> </div> <!-- 可选:添加Bootstrap风格的遮罩层 --> @if (_isOffcanvasOpen) { <div class="offcanvas-backdrop fade show" @onclick="ToggleOffcanvas"></div> }
修改Filter.razor的@code部分
[Parameter, EditorRequired] public required Enums.MenuItem? CurrentFilter { get; set; } [Parameter] public EventCallback<Enums.MenuItem> OnFilterSelected { get; set; } protected Enums.MenuItem currentMenuItem = Enums.MenuItem.HebrewPassOverOrCrossOver; private bool _isOffcanvasOpen; private void ToggleOffcanvas() { _isOffcanvasOpen = !_isOffcanvasOpen; } private async Task ButtonClicked(Enums.MenuItem filter) { currentMenuItem = filter; _isOffcanvasOpen = false; // 直接关闭Offcanvas await OnFilterSelected.InvokeAsync(filter); } // 其他代码
验证效果
两种方案都能实现点击菜单项后Offcanvas自动关闭的需求,同时不会破坏默认关闭按钮的功能。方案1贴近Bootstrap原生用法,方案2完全遵循Blazor的状态驱动逻辑,可根据项目习惯选择。
内容的提问来源于stack exchange,提问作者John Marsing
相关产品推荐
相关产品推荐

