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

前言

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

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

父子组件之间的通信

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

父组件操作子组件

在这里插入图片描述

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

父组件

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

<BigButton Text="提交" OnClick="@(e=>JS.InvokeVoidAsync("alert","我是一个警告框"))"/>
@inject IJSRuntime JS

最终效果
在这里插入图片描述

子组件与子组件的通信

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

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

大致效果是这样的:
在这里插入图片描述

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.Date</td>
                    <td>@item.TemperatureC</td>
                    <td>@item.TemperatureF</td>
                    <td>@item.Summary</td>
                </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 组件
    在这里插入图片描述
    定义一个 OnSelectItem 事件,当点击行时,即 @onclick 事件以后,触发 OnSelectItem 事件通知订阅方,并传入一个当前点击的数据项。

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

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

顺序大致如下
在这里插入图片描述
这样就完成了两个子组件之间的通信。

总结

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

插播广告

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

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我 Teacher 周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值