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

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于Hello Blazor:(11)全局截获事件执行的主要内容,如果未能解决你的问题,请参考以下文章

从 Blazor 组件 (.razor) 重定向到 Razor 页面 (.cshtml) [服务器端]

Hello Blazor:(15)使用bUnit进行单元测试

如何在 Blazor 中执行客户端 UI 事件

Blazor 3.1 嵌套的鼠标悬停事件

抑制触发的 Blazor 输入事件

Blazor Wasm 身份登录/注销事件