Blazor—— 父子组件、嵌套组件以及平行组件,他们到底是如何交互通信的呢?

目录

  • 前言
  • 父子组件之间的通信
    • 父组件操作子组件
    • 子组件变化通知父组件
  • 子组件与子组件的通信
  • 总结
  • 插播广告

前言

现在的前端开发,几乎都是基于组件的研发模式,即把每一块独立的功能切割成独立的组件,然后在大组件里根据需要自由组合这些小组件,使得组件的复用性提高,而小组件更容易测试和修改,从而提升研发的效率。比如按钮、文本框、对话框、点评星星等等都是可以被任意复用的小组件。

那么问题来了,组件之间是怎么进行通信呢?

父子组件之间的通信

当前组件即父组件,嵌套了一个封装好的组件,因此称这个组件为该组件的子组件。比如对话框。

父组件操作子组件

Blazor—— 父子组件、嵌套组件以及平行组件,他们到底是如何交互通信的呢?_第1张图片

<button class="btn btn-primary" @onclick="e=>modal.Show()">对话框button>

<BootModal @ref="modal">
    <HeadTemplate>
        <h4>你好h4>
    HeadTemplate>
    <BodyTemplate>
        弹出一个对话框
    BodyTemplate>
BootModal>

@code{
    BootModal modal;
}

我们使用了一个对话框的组件 BootModal,然后通过一个 @ref 关键字,可以让这个组件与该组件的实例进行关联,这样我们就可以通过代码操作这个实例了,比如调用方法。

回到我定义的一个按钮上,触发一个 @onclick 事件,然后调用这个 modalShow 方法弹出对话框。

子组件变化通知父组件

通过 EventCallback 事件的触发,使订阅该事件的对象得到触发后的通知。

在子组件中,可以定义一个 EventCallback 类型的属性,称为事件。

注意:这里的事件不是 C# 的 event 类型,而是一个 EventCallback 委托类型。

然后在需要的时候触发这个事件,被订阅的对象即可被执行,类似于订阅者模式。

[Parameter] public EventCallback On[EventName] { get; set;}

按照规范,事件命名应符合 On + 动词 的形式,例如 OnDelete/ OnCreate/OnClick 等。

子组件

封装了一个简单的按钮,并暴露了一个 OnClick 事件。

<button class="btn btn-warning btn-lg" @onclick="Click">
    @Text
button>

@code{
    [Parameter] public string Text { get; set; }

    [Parameter] public EventCallback OnClick { get; set; }

    public Task Click()
    {
        return OnClick.InvokeAsync(null);
    }
}

父组件

在父组件里订阅了这个事件。


@inject IJSRuntime JS

最终效果
Blazor—— 父子组件、嵌套组件以及平行组件,他们到底是如何交互通信的呢?_第2张图片

子组件与子组件的通信

示例场景:在一个页面中,左侧是一个列表(组件 List),右侧是详情(组件 Detail),当点击列表的数据时,右侧显示相应数据的详情。

从场景中可以看出,一个页面有 List 和 Detail 两个子组件,而现在是需要当 List 组件的某一行数据被选中,则 Detail 组件要显示这条数据的具体内容。

大致效果是这样的:
Blazor—— 父子组件、嵌套组件以及平行组件,他们到底是如何交互通信的呢?_第3张图片

Index 代码(即父组件代码)

<div class="row">
    <div class="col-6">
        <List OnSelectItem="Select"/>
    div>
    <div class="col">
        <Detail SelectedItem="SelectItem"/>
    div>
div>

@code{
    WeatherForecast SelectItem { get; set; }

    void Select(WeatherForecast item)
    {
        SelectItem = item;
    }
}

List 组件代码

<table class="table">
    <thead>
        <tr>
            <th>日期th>
            <th>摄氏度th>
            <th>华氏度th>
            <th>说明th>
        tr>
    thead>
    <tbody>
        @if (Data == null)
        {
            <tr>
                <td colspan="4">数据加载中...td>
            tr>
        }
        else
        {
            foreach (var item in Data)
            {
                <tr @onclick="e => SelectItem(item)">
                    <td>@item.Datetd>
                    <td>@item.TemperatureCtd>
                    <td>@item.TemperatureFtd>
                    <td>@item.Summarytd>
                tr>
            }
        }
    tbody>
table>


@inject WeatherForecastService WeatherForecastService
@code{
    IEnumerable<WeatherForecast> Data { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Data = await WeatherForecastService.GetForecastAsync(DateTime.Now);
    }

    [Parameter] public EventCallback<WeatherForecast> OnSelectItem { get; set; }

    async Task SelectItem(WeatherForecast item)
    {
        await OnSelectItem.InvokeAsync(item);
    }
}

Detail 组件代码

<h3>详情h3>
<hr />
<div class="form-group">
    日期:@SelectedItem?.Date
div>
<div class="form-group">
    摄氏度:@SelectedItem?.TemperatureC
div>
<div class="form-group">
    华氏度:@SelectedItem?.TemperatureF
div>
<div class="form-group">
    说明:@SelectedItem?.Summary
div>

@code {
    [Parameter]public WeatherForecast SelectedItem { get; set; }
}

原理介绍

  1. 在 List 组件
    Blazor—— 父子组件、嵌套组件以及平行组件,他们到底是如何交互通信的呢?_第4张图片
    定义一个 OnSelectItem 事件,当点击行时,即 @onclick 事件以后,触发 OnSelectItem 事件通知订阅方,并传入一个当前点击的数据项。

  2. 回到页面当中,OnSelectItem 事件订阅了一个方法 Select,把选中的项赋值给一个等候很久的 SelectItem 变量。

  3. 把该变量给 Detail 事先声明好的一个参数赋值。

顺序大致如下
Blazor—— 父子组件、嵌套组件以及平行组件,他们到底是如何交互通信的呢?_第5张图片
这样就完成了两个子组件之间的通信。

总结

通过子组件暴露的 EventCallback 事件,可以让父组件通过订阅事件来与子组件进行通信交互,这样就可以实现组件之间的互联互通操作,从而使组件之间更具有联动性。

插播广告

BootBlazorUI 基于 Bootstrap 样式为 Blazor 量身打造的前端组件库,不依赖 JQ 和 bootstrap.js,并支持 Mvc / Razor 页面和现在最新的 Blazor 。该组件立志于交互性和实用性,而不仅仅是一个静态UI库。

  • 源代码
  • Demo

你可能感兴趣的:(ASP.NET,Core)