乐趣区

关于后端:Blazor-组件之间使用-EventCallback-进行通信

Blazor 应用程序是互相交互的多个 Blazor 组件的汇合,咱们能够在其余父组件中应用子组件。在理论的应用程序中,将数据或事件信息从一个组件传递到另一组件是一种非常常见的场景。您可能会有一个页面,其中一个组件中产生的用户操作须要更新其余组件中的某些 UI。通常应用 EventCallback 委托来解决这种类型的通信。在本教程中,我将介绍如何应用 EventCallback 在父组件和子组件之间进行通信。

上面是应用 EventCallback 从子组件到父组件进行通信所波及的通用步骤。

在子组件中申明一个 EventCallback 或 EventCallback<T> 委托
在父组件中附加一个到子组件的 EventCallback 或 EventCallback<T> 的回调办法
当子组件想要与父组件通信时,能够应用以下办法之一调用父组件的回调办法。
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>

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

Title Minutes

@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;}

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

Blazor-Child-Component-that-will-Raise-Event

如果此时您点击子组件中的 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 属性减少了。

Blazor-Child-Component-Not-Updating-Parent-Component

让咱们应用下面提到的步骤在咱们的示例中改良一下子组件到父组件的通信,以便每次减少子组件中的 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>

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

Title Minutes

@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-Child-Component-Updating-Parent-Compoent-with-EventCallback

退出移动版