原文链接:https://blazor-university.com/components/component-events/
组件事件
源代码[1]
EventCallback<T> 类是一个特殊的 Blazor 类,可以作为参数公开,以便组件可以在发生感兴趣的事情时轻松通知使用者。
一旦声明了 EventCallback<T> 类型的公共属性并使用 [Parameter] 属性进行了修饰,使用组件就可以在 Razor 标记中指定触发事件时要调用的方法。
向 Counter 组件添加事件
在新的 Blazor 应用中,编辑 /Pages/Counter.razor 文件并添加新的回调参数。
[Parameter]
public EventCallback<int> OnMultipleOfThree { get; set; }这声明了一个名为 OnMultipleOfThree 的新 EventCallback,任何使用组件都可以注册它。<int> 指定事件回调发出的值将是 System.Int32。
现在,如果我们编辑 IncrementCount 方法,我们可以在计数器增加到 3 的倍数时发出此事件。
private async Task IncrementCount()
{currentCount++;if (currentCount % 3 == 0)await OnMultipleOfThree.InvokeAsync(currentCount);
}订阅 EventCallback
编辑 /Pages/Index.razor 页面,以便我们嵌入 Counter 组件并订阅其 OnMultipleOfThree 事件。将其标记更改为以下内容。
@page "/"Last multiple of three = @LastMultipleOfThree<Counter OnMultipleOfThree=@UpdateLastMultipleOfThreeValue/>@code
{int LastMultipleOfThree = 0;private void UpdateLastMultipleOfThreeValue(int value){LastMultipleOfThree = value;}
}第 9 行
声明一个 int 类型的类成员,它存储 3 值的最后一个倍数。
第 3 行
显示 LastMultipleOfThree 的值
第 5 行
嵌入 Counter 组件并设置其 OnMultipleOfThree 事件以在发出事件时执行 UpdateLastMultipleOfThreeValue 方法。
第 11 行
从事件接收到的值用于更新 LastMultipleOfThree 的值。
EventCallback和 .NET 事件之间的区别
单播与多播
最显着的区别是 EventCallback<T> 是单播事件处理程序,而 .NET 事件是多播。Blazor EventCallback<T> 旨在分配单个值,并且只能回调单个方法。
// Setting a Blazor EventCallback
<MyComponent SomeEvent=@MyMethodToCall/>// Setting a .NET event
MyComponent.SomeEvent += MyMethodToCall;
// Unscrubscribing from the event
MyComponent.SomeEvent -= MyMethodToCall;类与结构
.NET 事件(委托)是类,而 Blazor EventCallback<T> 是只读结构。与 .NET 委托不同,EventCallback<T> 不能为 null,因此在发出事件时无需进行任何 null 检查。
// Invoking a .NET event
MyNetEvent?.Invoke(this, someValue);// Invoking a CallbackEvent<T>
MyEventCallback.InvokeAsync(someValue);等待回调
标准 .NET 事件是同步的,而 Blazor EventCallback<T> 是异步的。正如我们在前面的示例代码中看到的,EventCallback<T>.InvokeAsync 返回一个可以等待的 Task。
Razor 标记兼容性
无法使用 [Parameter] 装饰标准 .NET 事件并通过 Razor 标记设置它,而使用 EventCallback<T> 可以。这使我们能够在视图标记本身中表达事件回调,这使得开发人员的意图更容易看到。
自动状态变化检测
每当从 EventCallback<T> 调用方法时,在方法执行后,Blazor 将在使用组件上执行 StateHasChanged(),以便在方法调用更改状态时重新渲染它。如果使用者的方法是通过标准 .NET 事件、Action或不是由 EventCallback<T> 发起的任何其他方法回调的,则不会发生这种情况。
例如,如果我们将一个新的 [Parameter] 添加到 Action<int> 类型的 Counter 组件中,并在当前计数是 2 的倍数时调用它,我们可以看到使用组件的渲染行为是如何受到影响的。
更改 Counter 组件以匹配以下代码:
@page "/counter"<h1>Counter</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick=IncrementCount>Click me</button>@code {private int currentCount = 0;[Parameter]public Action<int> OnMultipleOfTwoAction { get; set; }[Parameter]public EventCallback<int> OnMultipleOfThree { get; set; }private async Task IncrementCount(){currentCount++;if (currentCount % 2 == 0)OnMultipleOfTwoAction?.Invoke(currentCount);if (currentCount % 3 == 0)await OnMultipleOfThree.InvokeAsync(currentCount);}
}第 13 行
添加了
Action<int>类型的[Parameter]第 21-22 行
如果当前计数是 2 的倍数,则调用
OnMultipleOfTwoAction
现在更改 Index 组件,使其在值为 2 的倍数时设置回调方法,因此它也会存储并显示从 OnMultipleOfTwoAction 接收到的最后一个数字在使用的组件上。
@page "/"<ul><li>Last multiple of two = @LastMultipleOfTwo</li><li>Last multiple of three = @LastMultipleOfThree</li>
</ul><Counter OnMultipleOfThree=@UpdateLastMultipleOfThreeValue OnMultipleOfTwoAction=@UpdateLastMultipleOfTwoValue />@code
{int LastMultipleOfTwo = 0;int LastMultipleOfThree = 0;private Task UpdateLastMultipleOfThreeValue(int value){LastMultipleOfThree = value;return Task.CompletedTask;}private void UpdateLastMultipleOfTwoValue(int value){LastMultipleOfTwo = value;}
}第 13 行
定义一个新成员来存储从使用组件传递的最新“二的倍数”值
第 4 行
在用户界面中显示 LastMultipleOfTwo 的值
第 9 行
在使用的组件上设置
OnMultipleOfTwo以便在当前值是 2 的倍数时通知我们的组件第 24 行
记录使用组件通知我们的最后 2 的倍数
当我们现在运行应用程序并多次单击按钮时,我们会看到当通过 Action<int> 回调 UpdateLastMultipleOfTwoValue 时,视图没有更新,但是当下一次单击通过 EventCallback<int> 回调 UpdateLastMultipleOfThreeValue 时,视图更新并显示两者的最新值。

| 点击计数 | 回调执行 | 使用者重新渲染 |
|---|---|---|
| 1 | 无 | N/A |
| 2 | Action<int> | No |
| 3 | Action<int> EventCallback<int> | Yes |
| 4 | Action<int> | No |
| 5 | None | N/A |
| 6 | Action<int> EventCallback<int> | Yes |
EventCallback<T> 通常回调带有签名 private Task SomeName(T value)的方法——其中方法的暴露级别并不重要。但是,Blazor 将允许我们设置一个 EventCallback<T> 来回调具有几个变体的方法。
如果我们的方法不执行任何异步操作,那么下面的实现可能会开始变得乏味:
public Task SomethingHappenedInChildComponent(string value)
{// Do something with valuereturn Task.CompletedTask;
}因此,Blazor 将允许我们设置 EventCallback<T> 以回调具有 void 返回类型的方法。
public void SomethingHappenedInChildComponent(string value)
{// Do something with value
}有时我们只想知道一个事件何时发生,而不是对它传递的值感兴趣。Blazor 还将回调一个排除 value 参数的方法。
// Either
public void SomethingHappenedInChildComponent()
{// Do something that doesn't need the value
}// Or
public Task SomethingHappenedInChildComponent()
{// Do some asynchronous work that doesn't need the valuereturn SomeTask;
}浏览器 DOM 事件
呈现任何标记时,可以在呈现的 HTML 元素上分配标准 JavaScript 事件,以便执行我们自己的 Blazor C# 方法。例如,我们在其他地方的许多示例中使用了 @onclick 指令:
<button @onclick=ButtonClicked>Click me</button>这些事件指令在 Visual Studio 编辑器中具有完整的 IntelliSense 支持,因此开始键入 @ 符号应该会为我们提供可用指令的完整列表,以及标识事件在我们的事件处理程序中传递给我们的参数类类型的描述。DOM 事件以 @on 开头。

警告:在编写完全在服务器上运行的 Blazor 应用程序时,Blazor 将 hook 浏览器中的事件并将它们发送到服务器,以便可以调用我们的 C# 方法。这可能会导致频繁触发的事件(例如 onmousemove)明显变慢。
注意: 因为 C# 方法的 JavaScript 调用是异步的,这意味着在 C# 方法中我们不能像在 JavaScript 中那样取消事件。这是因为取消浏览器 DOM 事件是一个同步操作,当我们的 C# 被异步调用时,取消事件已经太迟了。
可用的 DOM 事件及其参数类型包括:
一般事件
| DOM 事件 | 参数类型 |
|---|---|
| onactivate | EventArgs |
| onbeforeactivate | EventArgs |
| onbeforedeactivate | EventArgs |
| ondeactivate | EventArgs |
| onended | EventArgs |
| onfullscreenchange | EventArgs |
| onfullscreenerror | EventArgs |
| onloadeddata | EventArgs |
| onloadedmetadata | EventArgs |
| onpointerlockchange | EventArgs |
| onpointerlockerror | EventArgs |
| onreadystatechange | EventArgs |
| onscroll | EventArgs |
焦点事件
| DOM 事件 | 参数类型 |
|---|---|
| onfocus | FocusEventArgs |
| onblur | FocusEventArgs |
| onfocusin | FocusEventArgs |
| onfocusout | FocusEventArgs |
鼠标事件
| DOM 事件 | 参数类型 |
|---|---|
| onmouseover | MouseEventArgs |
| onmouseout | MouseEventArgs |
| onmousemove | MouseEventArgs |
| onmousedown | MouseEventArgs |
| onmouseup | MouseEventArgs |
| onclick | MouseEventArgs |
| ondblclick | MouseEventArgs |
| oncontextmenu | MouseEventArgs |
| onwheel | WheelEventArgs |
| onmousewheel | WheelEventArgs |
拖动事件
| DOM 事件 | 参数类型 |
|---|---|
| ondrag | DragEventArgs |
| ondragend | DragEventArgs |
| ondragenter | DragEventArgs |
| ondragleave | DragEventArgs |
| ondragover | DragEventArgs |
| ondragstart | DragEventArgs |
| ondrop | DragEventArgs |
键盘事件
| DOM 事件 | 参数类型 |
|---|---|
| onkeydown | KeyboardEventArgs |
| onkeyup | KeyboardEventArgs |
| onkeypress | KeyboardEventArgs |
输入事件
| DOM 事件 | 参数类型 |
|---|---|
| onchange | ChangeEventArgs |
| oninput | ChangeEventArgs |
| oninvalid | EventArgs |
| onreset | EventArgs |
| onselect | EventArgs |
| onselectstart | EventArgs |
| onselectionchange | EventArgs |
| onsubmit | EventArgs |
剪贴板事件
| DOM 事件 | 参数类型 |
|---|---|
| onbeforecopy | EventArgs |
| onbeforecut | EventArgs |
| onbeforepaste | EventArgs |
| oncopy | ClipboardEventArgs |
| oncut | ClipboardEventArgs |
| onpaste | ClipboardEventArgs |
触摸事件
| DOM 事件 | 参数类型 |
|---|---|
| ontouchcancel | TouchEventArgs |
| ontouchend | TouchEventArgs |
| ontouchmove | TouchEventArgs |
| ontouchstart | TouchEventArgs |
| ontouchenter | TouchEventArgs |
| ontouchleave | TouchEventArgs |
指针事件
| DOM 事件 | 参数类型 |
|---|---|
| ongotpointercapture | PointerEventArgs |
| onlostpointercapture | PointerEventArgs |
| onpointercancel | PointerEventArgs |
| onpointerdown | PointerEventArgs |
| onpointerenter | PointerEventArgs |
| onpointerleave | PointerEventArgs |
| onpointermove | PointerEventArgs |
| onpointerout | PointerEventArgs |
| onpointerover | PointerEventArgs |
| onpointerup | PointerEventArgs |
多媒体事件
| DOM 事件 | 参数类型 |
|---|---|
| oncanplay | EventArgs |
| oncanplaythrough | EventArgs |
| oncuechange | EventArgs |
| ondurationchange | EventArgs |
| onemptied | EventArgs |
| onpause | EventArgs |
| onplay | EventArgs |
| onplaying | EventArgs |
| onratechange | EventArgs |
| onseeked | EventArgs |
| onseeking | EventArgs |
| onstalled | EventArgs |
| onstop | EventArgs |
| onsuspend | EventArgs |
| ontimeupdate | EventArgs |
| onvolumechange | EventArgs |
| onwaiting | EventArgs |
进度事件
| DOM 事件 | 参数类型 |
|---|---|
| onloadstart | ProgressEventArgs |
| ontimeout | ProgressEventArgs |
| onabort | ProgressEventArgs |
| onload | ProgressEventArgs |
| onloadend | ProgressEventArgs |
| onprogress | ProgressEventArgs |
| onerror | ErrorEventArgs |
参考资料
[1]
源代码: https://github.com/mrpmorris/blazor-university/tree/master/src/Components/EventCallbacks