前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >(13/30)Blazor系列:EventCallback, event from child to parent

(13/30)Blazor系列:EventCallback, event from child to parent

作者头像
沙漠尽头的狼
发布2021-12-21 18:10:48
发布2021-12-21 18:10:48
1.4K00
代码可运行
举报
文章被收录于专栏:Dotnet9Dotnet9
运行总次数:0
代码可运行

目前的4篇日志是来自我们写好的假数据,但正常来说不会这样做,而是有个按钮让用户点击了之后,增加或减少日志的数量。

增加的按钮会放在<Blog>,点击了「增加」按钮产生一条新的Post供用户输入,再让用户点击「确认」按钮储存日志。

删除的按钮则可以放在<Blog>,再在<Post>加入checkbox,让用户自己勾选要删除哪些Post;或是放在<Post>,点击删除按钮就删除该条日志。

新增按钮很简单,只要在<MyButton>加上@onclick事件即可,开始之前,先将版面稍作修改,顺便把FontSizeStyle移除。

Blog.razor

代码语言:javascript
代码运行次数:0
运行
复制
@page "/Blog"
@inherits BlogBase

@if (Blog == null)
{
    <p>Loading...</p>
}
else
{
    <div class="container">
        <div class="row">
            <div class="col pl-0">
                <label>博客名称</label>
                <input @bind-value="Blog.Name" class="form-control w-25"/>
                <MyButton value="Add" class="btn btn-info my-2" type="button" @onclick="Add"/>
            </div>
        </div>
        <div class="row">
            @if (Blog.Posts != null)
            {
                foreach (var post in Blog.Posts)
                {
                    <div class="col-md-3 border rounded p-3 mr-2 mb-2 w-25">
                        <CascadingValue Value="ColorStyle" Name="ColorStyle" IsFixed="true">
                            <Post Post="post" />
                        </CascadingValue>
                    </div>
                }
            }
        </div>
    </div>
}

C#部分则加入Add()方法,原来LoadData()的日志删除。

BlogBase.razor.cs

代码语言:javascript
代码运行次数:0
运行
复制
using BlazorServer.Models;
using Microsoft.AspNetCore.Components;

namespace BlazorServer.Pages;

public class BlogBase : ComponentBase
{
 public BlogModel? Blog { get; set; }

 public string? ColorStyle { get; set; } = "color: goldenrod";
 public string? FontSizeStyle { get; set; } = "color: goldenrod";

 protected override Task OnInitializedAsync()
 {
  LoadData();
  return base.OnInitializedAsync();
 }

 private void LoadData()
 {
  Blog = new BlogModel
  {
   Id = 1,
   Name = "我的博客",
   Posts = new List<PostModel>(),
   CreateDateTime = new DateTime(2021, 12, 14, 23, 46, 59)
  };
 }

 protected void Add()
 {
  Blog?.Posts?.Add(new PostModel());
 }
}

接着点击Add按钮,就可以看到日志条数增加了。

接着来做Delete功能,在Post.razor加入Delete按钮。

但问题来了,当我点击Delete按钮,<Blog>怎么知道我删除的是哪一条Post?这时候就需要Id可以识别,于是加入一个私有变量_postId,每次点击Add()都+1,正常来说PostId会跟着Post而不是由Blog产生,不过因为还没接触到数据库,所以先这样将就,后面连接数据库后就会改变。

为了验证是否正确,删除原来Post.razor注释的Post.Id,加入新样式的Post.Id,可以看到没有问题。

现在有了识别Id,又产生了新问题,要怎么让<Blog>收到Id?目前Id由<Blog>产生,所以没这问题,等后面Id由数据库产生后,<Blog>就不会知道Id了。前面说的都是从父组件传递数据到子组件的方法,我们现在要从子组件传数据到父组件,有办法做到反向传回去吗?

有的,那就是EventCallback,但是要把Delete改成<input>而非<MyButton>,因为EventCallback是由子组件传向父组件,如果用<MyButton>,Id的流向就必须先这样<Blog> => <Post> => <MyButton>,接着再用EventCallback反向<MyButton> => <Post> => <Blog>,实在太麻烦了。

先把Delete按钮改成<input>,加入@onclick="ReturnPostId"

接着在PostBase.razor.cs定义类型为EventCallback<int>的属性 GetPostId,记住一定要加上[Parameter]特性,因为这要被<Blog>调用。然后完整定义ReturnPostId()方法,里面做的就是GetPostId.InvokeAsync(Post!.PostId);,当外部传来的GetPostId被触发时,就将Post.PostId传给父组件也就是<Blog>

再在BlogBase.razor.cs定义同名方法GetPostId(int id),名字不需要一样,这边只是为了方便取同名,里面做的事情就是移除跟收到的Id有相同值的Post。

最后在Blog.razor<Post>GetPostId放入刚刚定义的方法就可以了。

我们来验证看看,先新增4条日志,再删除第2条,可以看到Id等于2的那条成功被删除了。

除了EventCallback,还有Delegate可以使用,不过局限性较大,我们也来试试看。

先在PostBase.razor.cs定义类型为Action<int>的属性 GetPostIdForDelegateReturnPostId()改用GetPostIdForDelegate

接着在Blog.razor<Post>改用GetPostIdForDelegate

但是实际点击后会发现不会删除日志,这是因为EventCallback会监控Component,一旦有变化就会重新渲染,委托则不会,委托必须在父组件也就是BlogBase.razor.cs调用StateHasChanged();方法,让父组件知道状态改变了。

另外委托一旦在子组件中定义了,父组件就必须要调用,否则会发生错误,EventCallback则没这问题。

站长注:当然,善于使用nullable也可以避免这种异常:

引用:

  1. Blazor EventCallback[1]
  2. EventCallback[2]
  3. Blazor Tutorial - Ep11 - EventCallback and how it is different from delegate[3]

出处:iT邦幫忙 作者:StrayaWorker 原文链接:https://ithelp.ithome.com.tw/articles/10262982 编辑:沙漠尽头的狼

注:本文代码通过 .NET 6 + Visual Studio 2022重构,可点击上面的原文链接与重构后代码比较学习,谢谢阅读。

参考资料

[1]

Blazor EventCallback: https://www.pragimtech.com/blog/blazor/blazor-eventcallback/

[2]

EventCallback: https://docs.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0#eventcallback-1

[3]

Blazor Tutorial - Ep11 - EventCallback and how it is different from delegate: https://www.youtube.com/watch?v=NQ7P0IPIqZk

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Dotnet9 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档