翻译自 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/)

Blazor 组件之间使用 EventCallback 进行通信相关推荐

  1. vue2.0 非父子组件之间的单一事件通信

    前言 vue官网指出: 通过使用事件中心,允许组件自由交流,无论组件处于组件树的哪一层.由于 Vue 实例实现了一个事件分发接口,你可以通过实例化一个空的 Vue 实例来实现这个目的. 也就是说 非父 ...

  2. Blazor 组件库开发指南

    翻译自 Waqas Anwar 2021年5月21日的文章 <A Developer's Guide To Blazor Component Libraries> [1] Blazor 的 ...

  3. 组件生命周期管理和通信方案

    随着移动互联网的快速发展,项目的迭代速度越来越快,需求改变越来越频繁,传统开发方式的工程所面临的一些,如代码耦合严重.维护效率低.开发不够敏捷等问题就凸现了出来.于是越来越多的公司开始推行" ...

  4. Vue组件之间数据通信12种方式

    目录 1.父组件向子组件传递数据 props 2.子组件向父组件传递数据($emit的用法) 3.兄弟组件通信 4.ref / $refs 5.eventBus事件总线($emit / $on) 6. ...

  5. vue中子组件和子组件之间怎么通信_vue.js组件之间如何通信?

    vue.js组件之间如何通信?下面本篇文章就来给大家介绍一下Vue.js组件间通信方式.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 平时在使用Vue框架的业务开发中,组件不仅仅要 ...

  6. React兄弟组件之间通信

    兄弟组件之间通信 React是只有单项数据流动模式,也就是只能父组件的数据传递给子组件,而没有办法将子组件的数据传递给父组件.那么如果想要两个子兄弟组件通信该怎么办呢? 答案是可以通过子组件向父组件推 ...

  7. 「后端小伙伴来学前端了」Vue中利用全局事件总线实现组件之间通信

    月亮啊月亮 你能照见南边,也能照见北边 照见她,你跟她说一声,就说我想她了. 前言 前一篇文章写了 vue 中利用 Props 实现组件之间的通信,那种方式是最简单也是最基础的组件之间的通信方式.父组 ...

  8. vue-自主研发非父子关系组件之间通信的问题

    相信很多人都知道解决组件间通信:vuex,今天的主角不是它. element-ui里解决组件间通信的思路:emitter.js ,但是如果你拿来你会发现它解决的是父子组件之间的通信问题.如果我们通信的 ...

  9. [vue] vue组件之间的通信都有哪些?

    [vue] vue组件之间的通信都有哪些? 父子Coms: 1/2/3 ..兄弟Coms: 4/5跨级Coms: 4/5/6/7props$emit/$on( $parents/$children ) ...

最新文章

  1. 人脸识别loss加强
  2. MySQL事务autocommit自动提交
  3. 每天学一点儿shell:xargs 命令
  4. 【Flink】 Flink 应用资源分配问题排查思路
  5. swagger : Could not resolve reference because of: Could not resolve pointer
  6. 史上最全的主流CPU性能排名
  7. MySQL8数据恢复
  8. matlab对样本方差区间估计,已知样本均值和样本方差做区间估计
  9. KMPlayer播放mkv视频不出声音的解决办法
  10. matlab绘制香农定理曲线,基于matla对香农公式仿真.doc
  11. 游戏直播视频太大了,怎么一键压缩视频?--QVE视频压缩
  12. 如何利用C#/C++调取创蓝253短信验证码
  13. idea合并分支代码怎么操作呢?
  14. 先学vba还是python-以Excel处理为目的学习python还是VBA?
  15. 【文献笔记】Viewing personalized video clips recommended by TikTok activates default mode network and vent
  16. 如何写一个拼写检查器-by Peter Norvig
  17. 如何寻找峰值及其位置(matlab)
  18. 删除 Zune 同步设置和历史记录教程
  19. 第5章 - 二阶多智能体系统的协同控制 --> 连续时间系统编队控制【程序代码】
  20. GitLab 及 Git 命令使用记录

热门文章

  1. jQuery的.live()和.die()
  2. Silverlight中开发和设计人员的合作文档信息
  3. wpf: DataGridTextColumn 数字格式显示,编辑时取消格式(StringFormat)
  4. 策略模式-Golang实现
  5. hdu-2612-Find a way(广搜,bfs)
  6. 使用qrcode类制作二维码
  7. #UnityTips# 2017.11.14
  8. oracle 基本异常的练习及各个错误码
  9. 使用badboy录制脚本 结合Jmeter一起测试。
  10. linux IP、端口连通性测试