Jam*_*mes 4 .net c# blazor blazor-server-side
我在 blazor 中有一个列表组件,其中有一个可折叠的创建部分,我希望当您单击以显示创建部分时,它将显示并滚动到创建部分。我的问题是 StateHasChanged() 没有及时更新 UI,因此当 javascript 触发时,我们尝试滚动到的元素还不存在。
显然我可以通过超时来解决这个问题,但是在 Blazor 中执行此操作的更干净的方法是什么?有没有办法说类似await StateUpdated()......
我的代码看起来像这样:
@page "/createlist"
<div>
<h3>My List</h3>
<a @onclick="ToggleAdding">
Create New
</a>
</div>
<ul>
@* list existing items... *@
</ul>
@if (IsAdding)
{
<div id="some-create-id">
<h3>Add Section</h3>
@* create controls here *@
</div>
}
@code {
public void ToggleAdding()
{
IsAdding = !IsAdding;
// Need something similar to StateHasChanged(), that is awaitable.
JsRuntime.InvokeVoidAsync("ScrollIn", new object[] { CreateElementId });
}
}
Run Code Online (Sandbox Code Playgroud)
js 很简单:
ScrollIn = id => {
let element = document.getElementById(id);
console.log(!!element ? "SCROLLIN" : "NO FOUND ELE", id);
if (!!element) { element.scrollIntoView(); }
}
Run Code Online (Sandbox Code Playgroud)
您需要从 进行 JavaScript 调用OnAfterRender(Async)。有关所有详细信息,请参阅ASP.NET Core Razor 组件生命周期。
我实际上会将 JavaScript 简化为:
ScrollElementIntoView = element => element.scrollIntoView();
Run Code Online (Sandbox Code Playgroud)
然后 C# 代码将如下所示,不使用任何硬编码 id:
@page "/scroll-test"
@inject IJSRuntime JsRuntime
<div>
<h3>My List</h3>
<a @onclick="ToggleAdding">
Create New
</a>
</div>
<ul>
@foreach (var x in Enumerable.Range(0, 100)) {
<li>@x</li>
}
</ul>
@if (IsAdding)
{
<div @ref="AddSectionRef">
<h3>Add Section</h3>
</div>
}
@code {
bool IsAdding { get; set; }
ElementReference AddSectionRef { get; set; }
List<Func<Task>> AfterRenderAsyncJobs = new();
private void ToggleAdding() {
IsAdding = !IsAdding;
AfterRenderAsyncJobs.Add(ScrollToAddSection);
StateHasChanged();
}
private async Task ScrollToAddSection() {
await JsRuntime.InvokeVoidAsync("ScrollElementIntoView", AddSectionRef);
}
protected override async Task OnAfterRenderAsync(bool firstRender) {
while (AfterRenderAsyncJobs.Any()) {
var job = AfterRenderAsyncJobs.First();
AfterRenderAsyncJobs.Remove(job);
await job.Invoke();
}
}
}
Run Code Online (Sandbox Code Playgroud)