【问题标题】:Blazor Virtualize component not rendering items on scrollBlazor Virtualize 组件未在滚动时呈现项目
【发布时间】:2021-04-01 16:04:21
【问题描述】:

我正在尝试使用 .Net 5 和 blazor 创建一个论坛网站。为了有效地加载论坛线程,我正在尝试使用新的Virtualize 组件。 我有一个问题。它只加载前 35 个项目,然后不响应滚动,所以我有一个巨大的空白空间,应该加载项目。

以下是代码页面。

请不要介意 LoadSvar 方法只是在列表中获取一个范围,它目前只是用于测试。最后它会调用一个有范围的服务。

    @page "/Traade/{traadid}"
    @using ViewModels.Traade
    @using Entities.Traad
    @inject ISvarService SvarService
    @inject ICurrentUserService CurrentUserService
    @if (_loaded)
    {
        <div class="container">
            <div class="margin-top-10px">
                <div class="row">
                    <div class="col-xl-3 space-content">
                        <div class="margin-bottom-10px">
                            <ForumOversigt></ForumOversigt>
                        </div>
                        <div>
                            <KoebSalgOversigt></KoebSalgOversigt>
                        </div>
                    </div>
                    <div class="col-xl-6 space-content">
                        <div class="margin-bottom-10px">
                            <MainSvar Traad="@_listSvarViewModel.Traad"></MainSvar>
                        </div>
                        <Virtualize ItemsProvider="@LoadSvar">
                            <ItemContent>
                                <SvarItem Svar="@context"
                                          IsAuthenticated="@_isAuthenticated"
                                          IsAdmin="@_listSvarViewModel.IsAdmin">
                                </SvarItem>
                            </ItemContent>
                            <Placeholder>
                                <LoadingScreen></LoadingScreen>
                            </Placeholder>
                        </Virtualize>
                        @* @foreach (var svar in _listSvarViewModel.Svar) *@
                        @* { *@
                        @*     _svarCount++; *@
                        @*     if (svar.IsHidden && !_listSvarViewModel.IsAdmin) *@
                        @*     { *@
                        @*         continue; *@
                        @*     } *@
                        @*     <div class="margin-bottom-10px"> *@
                        @*         @if (_svarCount == _total) *@
                        @*         { *@
                        @*             <span id="seneste"></span> *@
                        @*         } *@
                        @*         <SvarItem Svar="@svar" SvarCount="@_svarCount" IsAuthenticated="@_isAuthenticated"></SvarItem> *@
                        @*     </div> *@
                        @* } *@
                        <CascadingValue Value="this">
                            @if (_isAuthenticated)
                            {
                                <span id="seneste"></span>
                                <CreateSvar Traad="@_listSvarViewModel.Traad"></CreateSvar>                        }
                            else
                            {
                                <span id="seneste"></span>
                                <CreateSvarGuest Traad="@_listSvarViewModel.Traad"></CreateSvarGuest>                        }
                        </CascadingValue>
                    </div>
                    <div class="col-xl-3 space-content">
                        <FrontPageSettings></FrontPageSettings>
                    </div>
                </div>
            </div>
        </div>
    }
    else
    {
        <LoadingScreen/>
    }
    
    @code {
    
        [CascadingParameter]
        private Task<AuthenticationState> AuthenticationStateTask { get; set; }
    
        [Parameter]
        public string TraadId { get; set; }
    
        bool _loaded;
        ListSvarViewModel _listSvarViewModel = new();
        bool _isAuthenticated;
        int _svarCount;
        int _total;
    
        public override Task SetParametersAsync(ParameterView parameters)
        {
            _loaded = false;
            return base.SetParametersAsync(parameters);
        }
    
        protected override async Task OnParametersSetAsync()
        {
        //Get is admin from userService
            await UpdatePageInformation();
            _isAuthenticated = await CurrentUserService.IsAuthenticated();
            StateHasChanged();
        }
    
        public async Task UpdatePageInformation()
        {
            _listSvarViewModel = await SvarService.GetListSvarViewModel(int.Parse(TraadId), false);
            _total = _listSvarViewModel.Svar.Count;
        }
    
        protected override void OnAfterRender(bool firstRender)
        {
            if (firstRender) return;
            _loaded = true;
            _svarCount = 0;
            StateHasChanged();
        }
    
        private async ValueTask<ItemsProviderResult<Svar>> LoadSvar(ItemsProviderRequest request)
        {
            var numSvar = Math.Min(request.Count, _total - request.StartIndex);
            var listOfSvar = _listSvarViewModel.Svar.GetRange(request.StartIndex, numSvar);
            return new ItemsProviderResult<Svar>(listOfSvar, _total);
        }
    }

如您所见,它不再加载任何项目。

它会在渲染时触发 LoadSvar 方法,该方法会渲染 400 多个项目中的 35 个。但是滚动不会再次触发该方法以加载更多内容。

我在这里拉头发。 out 注释的foreach 循环不够快,所以我真的很想让Virtualize 组件工作。

【问题讨论】:

  • 浏览器控制台有错误吗?您是否尝试过使用 Items 而不是 ItemsProvider 来看看是否可行?
  • @user3071284 没有错误,是的,我都试过了。我可以再试一次并报告
  • 只是为了确认。回到项目没有帮助。

标签: blazor blazor-server-side .net-5


【解决方案1】:

OnAfterRender()OnParametersSetAsync() 更改为不要每次都调用StateHasChanged(),这不是一个好主意。另外,删除SetParametersAsync()

bool _loaded = false;

protected override async Task OnParametersSetAsync()
{
    await UpdatePageInformation();
    _isAuthenticated = await CurrentUserService.IsAuthenticated();
}

protected override void OnAfterRender(bool firstRender)
{
    if (firstRender)
    {
        _loaded = true;
        StateHasChanged();
    }
}

【讨论】:

  • 很公平。做过某事。它似乎提高了性能。谢谢。虚拟化仍然不起作用。我不知道为什么。
  • 你能分享一个展示这个问题的项目吗?
  • 我会尝试创建一个
【解决方案2】:

我认为这很可能是一个 CSS 问题(这也是为什么它很难调试的原因),您的屏幕截图显示了一些可以证实这一点的自定义样式。

Virtualize 组件将对 ItemsProvider 委托进行初始调用以获取第一批项目。此处请求的项目数取决于组件的当前高度、每个项目的高度(默认为 50 px)和过度扫描计数。组件也是通过这个初始调用来了解总项目数。

问题从这里开始。因为 Virtualize 组件现在知道项目的总数,它也可以计算自己的总高度(包括尚未渲染的项目)。如果 Virtualize 组件的高度无限增长以适应其内容(我在这里断言就是这种情况),那么将没有滚动条,并且由于您无法滚动,因此不会触发额外的提供程序调用。然后,您还会在前 35 个项目下方看到一个大空间,该空间应匹配 (400 - 35) * 50 像素的高度。

您可以通过将 style="height:300px" 之类的内容添加到 Virtualize 组件来轻松验证是否是这种情况。我还鼓励您使用浏览器的 DOM 浏览器来验证相关元素的尺寸,并检查哪个元素(如果有)在可能不应该显示滚动条的情况下显示滚动条。

编辑:再次查看您的代码,我相信 col-xl-6 很可能是这里的罪魁祸首。假设你使用 Bootstrap,col 是基于 flexbox 的,flex 项通常会无限增长以匹配它们的内容。

【讨论】:

  • 这似乎是可能的。我会试着调查你给我的信息。谢谢。
猜你喜欢
  • 2021-08-18
  • 2013-12-24
  • 2020-11-04
  • 2020-07-17
  • 2023-03-10
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多