Blazor 组件之间使用 EventCallback 进行通信

翻译自 Waqas Anwar 2021年3月28日的文章 《Communication between Blazor Components using EventCallback》 [1]

Blazor 应用程序是相互交互的多个 Blazor 组件的集合,我们可以在其他父组件中使用子组件。在实际的应用程序中,将数据或事件信息从一个组件传递到另一组件是一种十分常见的场景。您可能会有一个页面,其中一个组件中发生的用户操作需要更新其他组件中的某些 UI。通常使用 EventCallback 委托来处理这种类型的通信。在本教程中,我将介绍如何使用 EventCallback 在父组件和子组件之间进行通信。

下面是使用 EventCallback 从子组件到父组件进行通信所涉及的通用步骤。

  1. 在子组件中声明一个 EventCallback 或 EventCallback<T> 委托

  2. 在父组件中附加一个到子组件的 EventCallback 或 EventCallback<T> 的回调方法

  3. 当子组件想要与父组件通信时,可以使用以下方法之一调用父组件的回调方法。

  • InvokeAsync(Object) – 如果使用的是 EventCallback

  • InvokeAsync(T) – 如果使用的是 EventCallback<T>

为了理解上述步骤,让我们创建一个简单的待办事项列表(To Do List)示例。首先,在 Data 文件夹中创建以下 ToDo.cs 类。这是一个简单类,用于存储每个待办事项的 Title 和 Minutes 属性。Minutes 属性指定完成特定待办事项所需的时间。

ToDo.cs

public class ToDo
{public string Title { get; set; }public int Minutes { get; set; }
}

在项目中添加以下 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 代码块中,我们声明了两个属性 ToDos 和 TotalMinutes。其中 ToDos 属性存储待办事项的列表,TotalMinutes 存储所有待办事项花费分钟数的总和。

public List<ToDo> ToDos { get; set; }
public int TotalMinutes { get; set; }

接下来,我们在 Blazor 组件生命周期方法之一的名为 OnInitialized 的方法中使用一些待办事项对象来初始化我们的 ToDos 列表。我们还调用了 UpdateTotalMinutes 方法,该方法简单地计算 ToDos 列表中所有 ToDo 对象的 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 代码也非常简单,我们将 TotalMinutes 属性显示在带有页面标题的页面顶部。

<h5 class="float-right">Total Minutes: @TotalMinutes</h5>

我们还在页面上生成了一个 HTML 表格,接下来的 foreach 循环遍历 ToDos 列表并渲染一个名为 ToDoItem 的子组件,我们还使用其 Item 属性将每个 ToDo 对象传入子组件中。

@foreach (var todo in ToDos)
{<ToDoItem Item="todo" />
}

让我们在 Shared 文件夹中创建一个子组件 ToDoItem.razor 并在其中添加以下代码。该子组件有一个 Item 属性(我们在父组件的 foreach 循环中设置了属性)。该子组件简单地使用 <tr> 元素生成一个表格行,并在表格单元格中显示 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; }
}

运行该应用程序,您会看到一个类似于如下内容的页面:

如果此时您点击子组件中的 Add Minutes 按钮,则不会有任何反应,因为我们还没有将 click 事件与 Add Minutes 按钮关联起来。让我们更新一下 Add Minutes 按钮的代码,添加调用 AddMinute 方法的 @onclick 特性。

<button type="button" class="btn btn-success btn-sm float-right" @onclick="AddMinute">+ Add Minutes
</button>

当用户每次点击 Add Minutes 按钮时,事件处理方法 AddMinute 简单地将 Minutes 属性加 1。

public async Task AddMinute(MouseEventArgs e)
{Item.Minutes += 1; 
}

再次运行应用程序并尝试点击每个待办事项的 Add Minutes 按钮。您将注意到每个待办事项显示的分钟数会增加,但是顶部的总分钟数属性将保持不变。这是由于 TotalMinutes 属性是在父组件中计算的,而父组件并不知道子组件中的 Minutes 属性增加了。

让我们使用上面提到的步骤在我们的示例中改进一下子组件到父组件的通信,以便每次增加子组件中的 Minutes 时,能够相应地更新父组件的 UI。

§步骤1:在子组件中声明一个 EventCallback 或 EventCallback<T> 委托

第一步是在我们的子组件中声明 EventCallback<T> 委托。我们声明一个委托 OnMinutesAdded,并使用 MouseEventArgs 作为 T,因为它可以为我们提供有关按钮点击事件的额外信息。

[Parameter]
public EventCallback<MouseEventArgs> OnMinutesAdded { get; set; }

§步骤2:在父组件中附加一个到子组件的 EventCallback 或 EventCallback<T> 的回调方法

在这一步中,我们需要向在前面的步骤 1 中声明的子组件的 EventCallback 委托 OnMinutesAdded 附加一个回调方法。

<ToDoItem Item="todo" OnMinutesAdded="OnMinutesAddedHandler" />

在本例中我们使用的回调方法是 OnMinutesAddedHandler,该方法简单地调用同一个 UpdateTotalMinutes 方法,更新 TotalMinutes 属性。

public void OnMinutesAddedHandler(MouseEventArgs e)
{UpdateTotalMinutes();
}

§步骤3:当子组件需要与父组件通信时,使用 InvokeAsync(Object) 或 InvokeAsync(T) 方法调用父组件的回调方法。

在这一步中,我们需要调用父组件中的回调方法,因为我们希望每次用户点击 Add Minute 按钮时都会更新父组件 UI,所以最好的调用位置是在 AddMinute 方法中。

public async Task AddMinute(MouseEventArgs e)
{Item.Minutes += 1;await OnMinutesAdded.InvokeAsync(e);
}

这就是在 Blazor 中实现从子组件到父组件通信我们所要做的所有事情。以下是子组件 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();}
}

在浏览器中运行应用程序,并尝试增加任一待办事项的分钟数,您会注意到父组件将自动地实时更新总分钟数。

相关阅读:

  • Blazor Server 和 WebAssembly 应用程序入门指南

  • Blazor 组件入门指南

  • Blazor 数据绑定开发指南

  • Blazor 事件处理开发指南

  • Blazor 组件之间使用 EventCallback 进行通信(本文)


相关链接:

  1. https://www.ezzylearning.net/tutorial/communication-between-blazor-components-using-eventcallback Communication between Blazor Components using EventCallback ↩︎

作者 :Waqas Anwar
译者 :技术译民
出品 :技术译站(https://ITTranslator.cn/)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/299984.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

***教程十:数据库注入(上)

这一段的教程是笔者&#xff08;这里应该叫整理者&#xff09;由《***X档案》的教程中整理改编而来。不知道是什么时候&#xff0c;B/S结构的软件越来越普及。工程师们为了应对“用户皆白痴”的服务理念&#xff08;就是把用户想像成什么都不会&#xff09;&#xff0c;所以更加…

服务器精益改善系列,精益生产改善的内容是什么?

精益生产管理改善的内容包含了生产管理过程中的方方面面&#xff0c;如果可以准确理解的话&#xff0c;请从以下三个方面来理解&#xff1a;首先是精益生产管理六大产出&#xff0c;即PQCDSM&#xff0c;就是精益生产管理改善的第一层内容。其中PQCDSM分别代表了P&#xff1a;P…

当代大学查寝奇葩操作大赏 | 今日最佳

全世界只有3.14 %的人关注了青少年数学之旅&#xff08;图源 阿粪青&#xff0c;侵权删&#xff09;

mysql学习笔记之mysqlparameter(摘)

在.net中操作数据库的时候。 大家都喜欢用sqlparameter。 parameter是预编译的&#xff0c;可以加快速度&#xff0c;也可以防注入。 在使用mssql的时候用sqlparameter。 在使用mysql的时候使用mysqlparameters。 第一次使用mysql的时候&#xff0c;都经常犯一个错误 比如在使用…

.net LTS3.1升5.0和LTS6.0隐蔽的坑

下面这段代码就是把ascll为0到127值 &#xff0c;转成string&#xff0c;并判断在字符串中的位置&#xff0c;第5&#xff0c;6行代码分别用了两种IndexOf方法的重载。for (var i 0; i < 128; i) {var str1 ((char)i).ToString();var str2 $"---------------{str1}-…

Java正则表达式获取网页所有网址和链接文字

/*获取网址首页的所有网址和链接文字*/import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.Lis…

学习烂到留级,却凭着正经发表的第一篇论文,优雅斩获诺贝尔奖

全世界只有3.14 %的人关注了青少年数学之旅照片里的男人&#xff0c;得意但很谦逊&#xff0c;他是诺贝尔化学奖创设以来最年轻得主——田中耕一。诺贝尔奖通知的那一天 叮铃叮铃叮铃......正在加班的田中耕一掏出手机&#xff0c;这是一个陌生的跨洋电话。电话那头的外国人…

CakePHP Pagination (分頁功能) 加入自己的參數

如果還不知道什麼是 Pagination 或者還不了解如何使用&#xff0c;請參考&#xff1a; CakePHP Pagination (分頁功能) 。通常在管理後台實作時&#xff0c;常設定許多查詢條件來查詢資料&#xff0c;比如&#xff1a;起始、結束時間。通常這些參數都是用GET的方式在傳遞。以下…

基于事件驱动架构构建微服务第2部分:领域对象和业务规则

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part2-domain-objects-and-business-rules/在本文中&#xff0c;我将实现领域模型&#xff1a;EduSync.Speech.Domain这是包含核心域的最内层。它包含我们的领域对象和业…

qt客户端连接服务器不响应,qt判断tcp客户端是否连接服务器

qt判断tcp客户端是否连接服务器 内容精选换一换本章节指导您使用MongoDB客户端&#xff0c;通过弹性云服务器内网方式连接GaussDB(for Mongo)集群实例。操作系统使用场景&#xff1a;弹性云服务器的操作系统以Linux为例&#xff0c;客户端本地使用的计算机系统以Windows为例。目…

谈谈为什么我们需要云原生架构?

未来的软件&#xff0c;从诞生起&#xff0c;就是生在云上&#xff0c;长在云上的。这个说法绝对不是没有根据的&#xff0c;看看现在的互联网大厂在做的事情&#xff0c;你就知道了&#xff1a;阿里宣布成立云原生技术委员会&#xff0c;并投入数十亿大力推动阿里经济体全面云…

服务器系统设计方案,服务器集群方案设计

当前主流的集群方式包括以下几种&#xff1a;1.服务器主备集群方式服务器主-备方式由一台服务器在正常运行状态提供对外服务&#xff0c;其它集群节点作为备份机&#xff0c;备份机在正常状态下不接受外部的应用请求&#xff0c;实时对生产机进行检测&#xff0c;当生产机停机时…

快别发语音了! | 今日最佳

全世界只有3.14 %的人关注了青少年数学之旅&#xff08;图源千叶的堕天使绅士猫_呜喵0w0&#xff0c;侵权删&#xff09;我们无论遇到什么困难&#xff0c;都不要怕&#xff0c;微笑着面对它&#xff01;消除恐惧的最好方法就是面对恐惧&#xff01;

软件项目管理概览----版本控制

随着软件项目规模的不断扩大&#xff0c;项目管理的作用变得越来越重要。如果一个需要长期维护的项目不能得到很好的管理与控制&#xff0c;“软件腐败”就会发生&#xff0c;用不了多久&#xff0c;我们的程序可能就会像一团拌好的炸酱面一样难以找到头绪&#xff0c;维护的成…

设计模式之原型

原型模式介绍完整拷贝原型模式主要解决的问题就是创建重复对象&#xff0c;而这部分对象内容本身比较复杂&#xff0c;生成过程可能从库或者RPC接口中获取数据的耗时较长&#xff0c;因此采用克隆的方式节省时间。原型模式是一种创建型设计模式&#xff0c;使你能够复制已有对象…

华为服务器停止响应,windows服务器停止工作

windows服务器停止工作 内容精选换一换无法通过远程桌面连接裸金属服务器时&#xff0c;我们推荐您按照以下思路排查问题。检查是否符合登录条件检查网络是否正常检查防火墙配置是否正常远程访问端口配置异常尝试重启裸金属服务器确认是否已经按照裸金属服务器登录前的准备工作…

专题1.1——Exchange2013部署前准备条件

本专题将主要介绍Exchange2013从部署前准备、正式部署到应用配置和维护的整个过程。博文是我在自己做测试的过程中自己编写的&#xff0c;如果大家有什么意见或问题也欢迎一起讨论交流。废话不多说&#xff0c;下面进入正题。本节将主要介绍部署Exchange2013之前需要准备的先决…

这些让人看瞎了的设计!实力证明,数学才是世界的最终boss!

全世界只有3.14 %的人关注了青少年数学之旅昨天小天刷微博&#xff0c;看到了一组动图&#xff0c;一时间我都不知道是我的眼睛出了错&#xff0c;还是我的大脑反应不过来。奇了怪了&#xff01;怎么箭头反转了180后&#xff0c;还是原样&#xff01;问题到底出在哪里&#xff…

你真的了解低代码平台吗?

从 2020 年疫情之后&#xff0c;低代码这个概念就突然变得火热起来&#xff0c;各大自媒体纷纷推出介绍低代码的文章&#xff0c;InfoQ 也曾发表过一篇《为什么我说低代码是“行业毒瘤”&#xff1f;》引发了热议&#xff0c;明道的创始人任向晖随后在自己的公众号写文章《低代…

图像还可以这样玩!如何用OpenCV处理图像?

全世界只有3.14 % 的人关注了青少年数学之旅人工智能近年来呈现爆发式发展&#xff0c;计算机视觉和深度学习作为人工智能的两大支柱学科&#xff0c;近年来得到迅速发展。今天小天将带着大家走进计算机视觉&#xff01;所谓计算机视觉&#xff0c;就是指用摄影机和电脑代替人眼…