我有一個 Blazor 服務器應用程式,其中許多按鈕呈現在 for 回圈中。:
@for (int i = 0; i < _navItems.Count; i )
{
var localI = i;
<div class="col-3 mb-2">
<button @onclick="async () => await SetCurrentAsync(localI)" class="btn btn-sm">
@(i 1)
</button>
</div>
}
但是,Microsoft Docs 不建議在此處使用此方法,因為@onclick每次呈現組件時都會重新創建 中指定的委托:
Blazor 為回圈中的元素或組件重新創建 lambda 運算式委托可能會導致性能不佳。
此后檔案中提供的解決方案(以及鏈接的 GitHub 問題中提供的解決方案是創建一個Button具有Action包含委托的屬性的型別:
@foreach (var button in _buttons)
{
<div class="col-3 mb-2">
<button @key="button.Id" @onclick="button.Action" class="btn btn-sm">
@(i 1)
</button>
</div>
}
@code {
List<Button> _buttons = new();
List<NavItem> _items;
protected override async Task OnInitializedAsync()
{
_items = await GetItemsFromDb();
for(int i = 0; i < _items.Count; i )
{
var localI = i;
_buttons.Add(new Button
{
Id = item.Id,
Action = () => SetCurrent(localI);
});
}
}
class Button
{
public int Id { get; set; }
public Action Action { get; set; }
}
}
現在,@onclick參考Button.Action并解決了委托娛樂問題。
It is all fun and games until SetCurrent is not async.
Action will have to be changed to Func<Task> and buttons will have to be added using an async lambda expression:
_buttons.Add(new Button
{
Id = item.Id,
Action = async () => await SetCurrentAsync(localI);
});
And I still have to do:
@onclick="async() => await button.Action"
which would again recreate the delegates. How exactly can I do this for async methods?
uj5u.com熱心網友回復:
首先,做這樣的事情
@onclick="async () => await SetCurrentAsync(localI)"
是不必要的。您將任務包裝在任務中。
@onclick="()=> SetCurrentAsync(localI)"
作業原理完全一樣。Blazor 組件內部事件處理程式(用于按鈕單擊,...)包裝您在任務中傳遞的任何操作。最簡單的它看起來像這樣:
var task = InvokeAsync(EventMethod);
StateHasChanged();
if (!task.IsCompleted)
{
await task;
StateHasChanged();
}
你應該總是Func<Task>用來處理sync Task和Task。將 aAction與異步方法一起使用是不可以的 - 它會將 a 回傳void到 Blazor 組件事件處理程式。
有關作業演示,請參閱下面的代碼頁。有三個按鈕使用該模式
- 首先使用 async Task 呼叫一個 yield Task 方法。
- 第二個呼叫一個簡單的Task方法。
- 使用
Actionwithasync void演示 UI 更新問題。
關鍵是前兩個都將 a 回傳Task給 Blazor 組件事件處理程式,以便它可以正確處理組件呈現。
@page "/"
<h3>Button Actions</h3>
@foreach (var item in _buttonActions)
{
<div class="m-2">
<button class="btn btn-secondary" @onclick="item.Action">@item.Title</button>
</div>
}
<div>
@message
</div>
@code {
private List<ButtonAction> _buttonActions = new List<ButtonAction>();
protected override void OnInitialized()
{
{
var item = new ButtonAction() { Title = "Task" };
item.Action = () => GetValue(item);
_buttonActions.Add(item);
}
{
var item = new ButtonAction() { Title = "Async Task" };
item.Action = () => GetValueAsync(item);
_buttonActions.Add(item);
}
{
var item = new ButtonAction() { Title = "Async Void Task" };
item.MyAction = () => GetValueVoidAsync(item);
_buttonActions.Add(item);
}
}
private string message;
public Task GetValue(ButtonAction item)
{
message = $"Value: {item.Id}";
return Task.CompletedTask;
}
public async Task GetValueAsync(ButtonAction item)
{
await Task.Yield();
message = $"Value: {item.Id}";
}
public async void GetValueVoidAsync(ButtonAction item)
{
await Task.Yield();
message = $"Value: {item.Id}";
}
public class ButtonAction
{
public string Title { get; set; }
public Guid Id { get; } = Guid.NewGuid();
public Func<Task> Action { get; set; }
public Action MyAction { get; set; }
}
}
關于性能,我認為這真的取決于“多少?”。如果我可能有 25 個編輯和查看按鈕,我不使用編輯串列的模式。我從來沒有注意到一個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/353489.html
標籤:c# blazor blazor-server-side
上一篇:如何反向映射在AutomapperC#中顯式映射的物體的多個成員?
下一篇:UTF-8洗掉BOM
