Hello Blazor:(11)全局截获事件执行

前言

在Blazor中,我们使用@on{DOM EVENT}="{DELEGATE}"这样的Razor语法在组件标记中指定委托事件处理程序:

<button @onclick="IncrementCount">Click me</button>

但是没有提供解除委托的方法。

比如,我们需要在某种条件下才执行事件处理:

有不有阻止事件触发的方案呢?

常规解决方案

我们可以在委托事件处理程序中加上判断:

<button @onclick="()=> { if (!checkedValue) { IncrementCount(); } }">Click me</button>

但是,如果有多个组件都需要加上这个判断,这样写感觉比较繁琐。

有不有更简化的方法?

深入分析

在前面的文章中,我们已经知道Blazor组件实际上会编译成C#语句。

在obj\Debug\net5.0\Razor\Pages目录下,可以看到@onclick="IncrementCount"对应的代码如下:

__builder.AddAttribute(13, "onclick",
  Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, IncrementCount));

原来是创建了一个EventCallback事件回调。

在github上查找到EventCallback.Factory.Create的实现源码[1]

private EventCallback CreateCore(object receiver, MulticastDelegate callback)
{
    return new EventCallback(callback?.Target as IHandleEvent ?? receiver as IHandleEvent, callback);
}

上面代码的意思,如果callback的来源是IHandleEvent,则实际回调的是IHandleEvent实现。

也就是说,只需要组件继承IHandleEvent,那么就可以控制组件上所有的事件回调了。

实现

修改代码如下:

@implements IHandleEvent

Task IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, object arg)
{
    System.Console.WriteLine("HandleEven");
    return callback.InvokeAsync(arg);
}

private void IncrementCount()
{
    System.Console.WriteLine("Clicked...");
    currentCount++;
}

运行后可以看到,确实先执行的HandleEventAsync,再执行的@onclick实现:

结论

通过本文,我们可以了解到,只要在组件上继承IHandleEvent,就可以实现全局截获事件回调。

但是,你会发现有一个问题,Current count没有发生变化!

这是为什么呢?请听下回分解!

参考资料

[1]

实现源码: https://github.com/dotnet/aspnetcore/blob/main/src/Components/Components/src/EventCallbackFactory.cs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值