Blazor Virtualize组件渲染完成后触发JS方法的实现方案
解决方案:监听Blazor Virtualize渲染完成并初始化Popover
核心思路
利用Virtualize组件的ItemsProvider回调标记新数据加载完成,结合OnAfterRenderAsync在DOM更新后触发JS初始化逻辑,同时通过自定义属性避免重复绑定Popover。
步骤1:组件代码实现
@inject IJSRuntime JSRuntime <table class="table"> <thead> <tr> <th>ID</th> <th>内容</th> </tr> </thead> <tbody> <Virtualize ItemsProvider="LoadItems" Context="item"> <tr> <td>@item.Id</td> <td> <!-- 给需要Popover的元素加未初始化标记 --> <span class="text-primary" data-bs-toggle="popover" data-bs-content="@item.Detail" data-popover-initialized="false"> @item.Name </span> </td> </tr> </Virtualize> </tbody> </table> @code { // 标记是否需要重新初始化Popover private bool _needsPopoverSetup; // Virtualize的数据加载回调 private async ValueTask<ItemsProviderResult<MyDataItem>> LoadItems(ItemsProviderRequest request) { // 替换为你的实际数据加载逻辑 var items = await FetchPaginatedData(request.StartIndex, request.Count); var totalCount = await GetTotalItemCount(); // 新数据加载完成,标记需要初始化Popover _needsPopoverSetup = true; StateHasChanged(); return new ItemsProviderResult<MyDataItem>(items, totalCount); } protected override async Task OnAfterRenderAsync(bool firstRender) { // 首次渲染或新数据加载后,执行Popover初始化 if (firstRender || _needsPopoverSetup) { await JSRuntime.InvokeVoidAsync("setupPopovers"); _needsPopoverSetup = false; } } // 以下为模拟数据方法,请替换为实际业务逻辑 private async Task<List<MyDataItem>> FetchPaginatedData(int startIndex, int count) { await Task.Delay(100); return Enumerable.Range(startIndex, count) .Select(i => new MyDataItem { Id = i, Name = $"条目{i}", Detail = $"条目{i}的详细描述内容" }) .ToList(); } private async Task<int> GetTotalItemCount() { await Task.Delay(100); return 150; } public class MyDataItem { public int Id { get; set; } public string Name { get; set; } public string Detail { get; set; } } }
步骤2:JS初始化逻辑
在wwwroot/js目录下创建popover-utils.js,并在_Layout.cshtml中引入:
window.setupPopovers = function() { // 只选择未初始化的Popover元素,避免重复绑定 const uninitializedElements = document.querySelectorAll('[data-bs-toggle="popover"][data-popover-initialized="false"]'); uninitializedElements.forEach(el => { // 用Popper.js创建Bootstrap风格的Popover new bootstrap.Popover(el, { trigger: 'hover', placement: 'top', html: false }); // 标记为已初始化 el.setAttribute('data-popover-initialized', 'true'); }); }
关键说明
- 触发时机:Virtualize每次滚动加载新数据时,
ItemsProvider会被调用,此时标记_needsPopoverSetup并触发状态变更,确保组件重新渲染后执行OnAfterRenderAsync。 - 性能优化:通过
data-popover-initialized属性过滤已初始化元素,避免重复创建Popover实例。 - 兼容性:适配Bootstrap 5 CSS和Popper.js的原生API,无需引入第三方Blazor库。
内容的提问来源于stack exchange,提问作者Grandizer
相关产品推荐
相关产品推荐

