Blazor 组件之间使用 EventCallback 进行通信
翻譯自 Waqas Anwar 2021年3月28日的文章?《Communication between Blazor Components using EventCallback》?[1]
Blazor 應(yīng)用程序是相互交互的多個(gè) Blazor 組件的集合,我們可以在其他父組件中使用子組件。在實(shí)際的應(yīng)用程序中,將數(shù)據(jù)或事件信息從一個(gè)組件傳遞到另一組件是一種十分常見的場(chǎng)景。您可能會(huì)有一個(gè)頁面,其中一個(gè)組件中發(fā)生的用戶操作需要更新其他組件中的某些 UI。通常使用 EventCallback 委托來處理這種類型的通信。在本教程中,我將介紹如何使用 EventCallback 在父組件和子組件之間進(jìn)行通信。
下面是使用 EventCallback 從子組件到父組件進(jìn)行通信所涉及的通用步驟。
在子組件中聲明一個(gè)?EventCallback?或?EventCallback<T>?委托
在父組件中附加一個(gè)到子組件的?EventCallback?或?EventCallback<T>?的回調(diào)方法
當(dāng)子組件想要與父組件通信時(shí),可以使用以下方法之一調(diào)用父組件的回調(diào)方法。
InvokeAsync(Object)?– 如果使用的是?EventCallback
InvokeAsync(T)?– 如果使用的是?EventCallback<T>
為了理解上述步驟,讓我們創(chuàng)建一個(gè)簡(jiǎn)單的待辦事項(xiàng)列表(To Do List)示例。首先,在?Data?文件夾中創(chuàng)建以下?ToDo.cs?類。這是一個(gè)簡(jiǎn)單類,用于存儲(chǔ)每個(gè)待辦事項(xiàng)的?Title?和?Minutes?屬性。Minutes?屬性指定完成特定待辦事項(xiàng)所需的時(shí)間。
ToDo.cs
public class ToDo {public string Title { get; set; }public int Minutes { get; set; } }在項(xiàng)目中添加以下?ToDoList.razor?組件,并在其中編寫以下代碼:
ToDoList.razor
@page "/todos" @using BlazorEventHandlingDemo.Data<div class="row"><div class="col"><h3>To Do List</h3></div><div class="col"><h5 class="float-right">Total Minutes: @TotalMinutes</h5></div> </div><br /> <table class="table"><tr><th>Title</th><th>Minutes</th><th></th></tr>@foreach (var todo in ToDos){<ToDoItem Item="todo" />} </table>@code {public List<ToDo> ToDos { get; set; }public int TotalMinutes { get; set; }protected override void OnInitialized(){ToDos = new List<ToDo>(){new ToDo() { Title = "Analysis", Minutes = 40 },new ToDo() { Title = "Design", Minutes = 30 },new ToDo() { Title = "Implementation", Minutes = 75 },new ToDo() { Title = "Testing", Minutes = 40 }};UpdateTotalMinutes();}public void UpdateTotalMinutes(){TotalMinutes = ToDos.Sum(x => x.Minutes);} }在上面的?@code?代碼塊中,我們聲明了兩個(gè)屬性?ToDos?和?TotalMinutes。其中?ToDos?屬性存儲(chǔ)待辦事項(xiàng)的列表,TotalMinutes?存儲(chǔ)所有待辦事項(xiàng)花費(fèi)分鐘數(shù)的總和。
public List<ToDo> ToDos { get; set; } public int TotalMinutes { get; set; }接下來,我們?cè)?Blazor 組件生命周期方法之一的名為?OnInitialized?的方法中使用一些待辦事項(xiàng)對(duì)象來初始化我們的?ToDos?列表。我們還調(diào)用了?UpdateTotalMinutes?方法,該方法簡(jiǎn)單地計(jì)算 ToDos 列表中所有 ToDo 對(duì)象的?Minutes?屬性的總和。
protected override void OnInitialized() {ToDos = new List<ToDo>(){new ToDo() { Title = "Analysis", Minutes = 40 },new ToDo() { Title = "Design", Minutes = 30 },new ToDo() { Title = "Implementation", Minutes = 75 },new ToDo() { Title = "Testing", Minutes = 40 }};UpdateTotalMinutes(); }HTML 代碼也非常簡(jiǎn)單,我們將?TotalMinutes?屬性顯示在帶有頁面標(biāo)題的頁面頂部。
<h5 class="float-right">Total Minutes: @TotalMinutes</h5>我們還在頁面上生成了一個(gè) HTML 表格,接下來的?foreach?循環(huán)遍歷?ToDos?列表并渲染一個(gè)名為?ToDoItem?的子組件,我們還使用其?Item?屬性將每個(gè)?ToDo?對(duì)象傳入子組件中。
@foreach (var todo in ToDos) {<ToDoItem Item="todo" /> }讓我們?cè)?Shared?文件夾中創(chuàng)建一個(gè)子組件?ToDoItem.razor?并在其中添加以下代碼。該子組件有一個(gè)?Item?屬性(我們?cè)诟附M件的?foreach?循環(huán)中設(shè)置了屬性)。該子組件簡(jiǎn)單地使用?<tr>?元素生成一個(gè)表格行,并在表格單元格中顯示?Title?和?Minutes?屬性。
ToDoItem.razor
@using BlazorEventHandlingDemo.Data <tr><td>@Item.Title</td><td>@Item.Minutes</td><td><button type="button" class="btn btn-success btn-sm float-right">+ Add Minutes</button></td> </tr>@code {[Parameter]public ToDo Item { get; set; } }運(yùn)行該應(yīng)用程序,您會(huì)看到一個(gè)類似于如下內(nèi)容的頁面:
如果此時(shí)您點(diǎn)擊子組件中的?Add Minutes?按鈕,則不會(huì)有任何反應(yīng),因?yàn)槲覀冞€沒有將 click 事件與?Add Minutes?按鈕關(guān)聯(lián)起來。讓我們更新一下?Add Minutes?按鈕的代碼,添加調(diào)用?AddMinute?方法的?@onclick?特性。
<button type="button" class="btn btn-success btn-sm float-right" @onclick="AddMinute">+ Add Minutes </button>當(dāng)用戶每次點(diǎn)擊 Add Minutes 按鈕時(shí),事件處理方法?AddMinute?簡(jiǎn)單地將 Minutes 屬性加 1。
public async Task AddMinute(MouseEventArgs e) {Item.Minutes += 1; }再次運(yùn)行應(yīng)用程序并嘗試點(diǎn)擊每個(gè)待辦事項(xiàng)的?Add Minutes?按鈕。您將注意到每個(gè)待辦事項(xiàng)顯示的分鐘數(shù)會(huì)增加,但是頂部的總分鐘數(shù)屬性將保持不變。這是由于?TotalMinutes?屬性是在父組件中計(jì)算的,而父組件并不知道子組件中的?Minutes?屬性增加了。
讓我們使用上面提到的步驟在我們的示例中改進(jìn)一下子組件到父組件的通信,以便每次增加子組件中的?Minutes?時(shí),能夠相應(yīng)地更新父組件的 UI。
§步驟1:在子組件中聲明一個(gè)?EventCallback?或?EventCallback<T>?委托
第一步是在我們的子組件中聲明?EventCallback<T>?委托。我們聲明一個(gè)委托?OnMinutesAdded,并使用?MouseEventArgs?作為?T,因?yàn)樗梢詾槲覀兲峁┯嘘P(guān)按鈕點(diǎn)擊事件的額外信息。
[Parameter] public EventCallback<MouseEventArgs> OnMinutesAdded { get; set; }§步驟2:在父組件中附加一個(gè)到子組件的?EventCallback?或?EventCallback<T>?的回調(diào)方法
在這一步中,我們需要向在前面的步驟 1 中聲明的子組件的?EventCallback?委托?OnMinutesAdded?附加一個(gè)回調(diào)方法。
<ToDoItem Item="todo" OnMinutesAdded="OnMinutesAddedHandler" />在本例中我們使用的回調(diào)方法是?OnMinutesAddedHandler,該方法簡(jiǎn)單地調(diào)用同一個(gè)?UpdateTotalMinutes?方法,更新?TotalMinutes?屬性。
public void OnMinutesAddedHandler(MouseEventArgs e) {UpdateTotalMinutes(); }§步驟3:當(dāng)子組件需要與父組件通信時(shí),使用?InvokeAsync(Object)?或?InvokeAsync(T)?方法調(diào)用父組件的回調(diào)方法。
在這一步中,我們需要調(diào)用父組件中的回調(diào)方法,因?yàn)槲覀兿M看斡脩酎c(diǎn)擊?Add Minute?按鈕時(shí)都會(huì)更新父組件 UI,所以最好的調(diào)用位置是在?AddMinute?方法中。
public async Task AddMinute(MouseEventArgs e) {Item.Minutes += 1;await OnMinutesAdded.InvokeAsync(e); }這就是在 Blazor 中實(shí)現(xiàn)從子組件到父組件通信我們所要做的所有事情。以下是子組件?ToDoItem.razor?的完整代碼:
ToDoItem.razor
@using BlazorEventHandlingDemo.Data <tr><td>@Item.Title</td><td>@Item.Minutes</td><td><button type="button" class="btn btn-success btn-sm float-right" @onclick="AddMinute">+ Add Minutes</button></td> </tr>@code {[Parameter]public ToDo Item { get; set; }[Parameter]public EventCallback<MouseEventArgs> OnMinutesAdded { get; set; }public async Task AddMinute(MouseEventArgs e){Item.Minutes += 1;await OnMinutesAdded.InvokeAsync(e);} }以下是父組件?ToDoList.razor?的完整代碼:
ToDoList.razor
@page "/todos" @using BlazorEventHandlingDemo.Data<div class="row"><div class="col"><h3>To Do List</h3></div><div class="col"><h5 class="float-right">Total Minutes: @TotalCount</h5></div> </div><br /> <table class="table"><tr><th>Title</th><th>Minutes</th><th></th></tr>@foreach (var todo in ToDos){<ToDoItem Item="todo" OnMinutesAdded="OnMinutesAddedHandler" />} </table>@code {public List<ToDo> ToDos { get; set; }public int TotalCount { get; set; }protected override void OnInitialized(){ToDos = new List<ToDo>(){new ToDo() { Title = "Analysis", Minutes = 40 },new ToDo() { Title = "Design", Minutes = 30 },new ToDo() { Title = "Implementation", Minutes = 75 },new ToDo() { Title = "Testing", Minutes = 40 }};UpdateTotalMinutes();}public void UpdateTotalMinutes(){TotalCount = ToDos.Sum(x => x.Minutes);}public void OnMinutesAddedHandler(MouseEventArgs e){UpdateTotalMinutes();} }在瀏覽器中運(yùn)行應(yīng)用程序,并嘗試增加任一待辦事項(xiàng)的分鐘數(shù),您會(huì)注意到父組件將自動(dòng)地實(shí)時(shí)更新總分鐘數(shù)。
相關(guān)閱讀:
Blazor Server 和 WebAssembly 應(yīng)用程序入門指南
Blazor 組件入門指南
Blazor 數(shù)據(jù)綁定開發(fā)指南
Blazor 事件處理開發(fā)指南
Blazor 組件之間使用 EventCallback 進(jìn)行通信(本文)
相關(guān)鏈接:
https://www.ezzylearning.net/tutorial/communication-between-blazor-components-using-eventcallback?Communication between Blazor Components using EventCallback???
作者 :Waqas Anwar
譯者 :技術(shù)譯民
出品 :技術(shù)譯站(https://ITTranslator.cn/)
總結(jié)
以上是生活随笔為你收集整理的Blazor 组件之间使用 EventCallback 进行通信的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式之建造者
- 下一篇: 基于事件驱动架构构建微服务第2部分:领域