使用 Blazor Virtualize 组件加载列表时滚动到底部

问题描述 投票:0回答:1
javascript c# scroll blazor
1个回答
0
投票

理性

名为

scrollToBottom
的 JavaScirpt 函数未被调用,因为组件
Virtualize
正在内部调用
StateHasChanged()
事件。根据
Microsoft
StateHasChanged()
事件是 Virtualize 组件调用的唯一状态更改检测器。要检测状态更改,必须实施解决方法。

解决方案

@page "/"
@inject IJSRuntime JS;

<div id="messages-container" style="overflow-y: scroll; height:500px">
    <Virtualize Context="message" ItemsProvider="@((ItemsProviderRequest request)=>{
                                                    ValueTask<ItemsProviderResult<Messages>> result = GetMessages(request);
                                                    ContentChanged();
                                                    return result;
                                                    })">
        <p>@message.Content</p>
    </Virtualize>
</div>

<script>
    function scrollToBottom() {
        var objDiv = document.getElementById("messages-container");
        objDiv.scrollTop = objDiv.scrollHeight;
        console.log(objDiv);
    }
</script>

@code{
    Messages[] messages { get; set; }
    public bool initialScroll = true;

    public class Messages
    {
        public string? Id { get; set; }
        public string? Content { get; set; }
    }

    public async void ContentChanged()
    {
        if (initialScroll)
        {
            initialScroll = false;

            // Scroll to the end of the first page
            await JS.InvokeAsync<string>("scrollToBottom");

            // Scroll to the last page
            await JS.InvokeAsync<string>("scrollToBottom");
        }
    }


    public Task<Messages[]> GenerateDummyMessages()
    {
        Messages[] messages = new Messages[1000];
        for (int i = 0; i < 1000; i++)
        {
            messages[i] = new Messages();
            messages[i].Id = i.ToString();
            messages[i].Content = $"This is the message nr. {i}";
        }
        return Task.FromResult(messages);
    }


    public Task<Messages[]> GetDummyMessages(int start, int count)
    {
        int index = 0;
        Messages[] request = new Messages[count];

        while (start < messages.Length && index < request.Length)
        {
            request[index] = messages[start];
            index++;
            start++;
        }

        return Task.FromResult(request);
    }


    public async ValueTask<ItemsProviderResult<Messages>> GetMessages(ItemsProviderRequest request)
    {
        int max_size = 1000;

        DateTime start = DateTime.Now;

        if (messages == null)
            messages = await GenerateDummyMessages();

        // Render the number of elements requested that is equal to the page size from a start index
        Messages[] messages_ = await GetDummyMessages(request.StartIndex, request.Count);

        // SIMULATE DELAY
        while ((DateTime.Now - start).TotalSeconds < 2);

        return new ItemsProviderResult<Messages>(messages_, max_size);
    }
}

Virtualize
组件中,必须修改
ItemsProvider
委托回调。项目提供程序必须通过 Blazor 属性实现匿名 lambda 函数,该属性请求将
ItemsProviderRequest
作为参数传递给回调方法,在本例中为
GetMessages
。在匿名 lambda 函数体内,调用回调方法,其结果存储在变量中,调用执行名为
ContentChanged
的滚动功能的方法,然后由匿名函数返回回调方法的结果
Virtualize
组件的 lambda 函数用于渲染内容。

    <Virtualize Context="message" ItemsProvider="@((ItemsProviderRequest request)=>{
                                                    ValueTask<ItemsProviderResult<Messages>> result = GetMessages(request);
                                                    ContentChanged();
                                                    return result;
                                                    })">
        <p>@message.Content</p>
    </Virtualize>

ContentChanged
方法中,JavaScript 函数被调用两次,第一次滚动到渲染元素第一部分的末尾,第二次滚动到底部以请求加载最后一部分元素。

    public bool initialScroll = true;

    public async void ContentChanged()
    {
        if (initialScroll)
        {
            initialScroll = false;

            // Scroll to the end of the first page
            await JS.InvokeAsync<string>("scrollToBottom");

            // Scroll to the last page
            await JS.InvokeAsync<string>("scrollToBottom");
        }
    }

模拟消息提取服务的方法,模拟延迟2秒。

    public async ValueTask<ItemsProviderResult<Messages>> GetMessages(ItemsProviderRequest request)
    {
        int max_size = 1000;

        DateTime start = DateTime.Now;

        if (messages == null)
            messages = await GenerateDummyMessages();

        // Render the number of elements requested that is equal to the page size from a start index
        Messages[] messages_ = await GetDummyMessages(request.StartIndex, request.Count);

        // SIMULATE DELAY
        while ((DateTime.Now - start).TotalSeconds < 2);

        return new ItemsProviderResult<Messages>(messages_, max_size);
    }

结果

Scroll down result

© www.soinside.com 2019 - 2024. All rights reserved.