名为
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);
}