当前位置: 首页 > news >正文

第三章 组件(6)- 事件处理

事件的常规使用

一、事件处理程序

@on{DOM事件}:为HTML元素的指定事件设置事件处理程序。

Razor组件中,在HTML元素上,可以看到一系列@on{DOM事件}指令,这些都是微软根据Html元素对应的DOM事件进行封装的一种机制,其类型为EventCallback<T>EventCallback(事件回调,也可以称为事件处理程序)

  • 支持返回Task的事件处理程序
  • 允许组件之间进行类型安全的事件传递和回调。
  • 注意,EventCallback<T>EventCallback事件处理程序执行后,会自动刷新 UI,这是 Blazor 的一个核心特性,称为“自动状态管理”。
  • 事件处理程序仅在交互模式下会执行。

在这里插入图片描述

  • 示例1-设置事件处理程序(同步)

    @page "/counter"
    @rendermode InteractiveServer
    
    <div>
        <button @onclick="Test">按钮</button>
    </div>
    
    @count
    
    @code{
        private int count = 0;
        private void Test(MouseEventArgs args) //这个args参数,如果不需要,可以不声明
        {
            count += 1;
        }
    }
    
  • 示例2-设置事件处理程序(异步)

    @page "/event-handler"
    
    <PageTitle>Event Handler</PageTitle>
    
    <h1>Event Handler Example</h1>
    
    <h2>@headingValue</h2>
    
    <p>
        <button @onclick="UpdateHeading">
            Update heading
        </button>
    </p>
    
    @code {
        private string headingValue = "Initial heading";
    
        private async Task UpdateHeading()
        {
            await Task.Delay(2000);
            headingValue = $"New heading ({DateTime.Now})";
        }
    }
    
  • 示例3-组件之间通过组件参数传递事件处理程序

    @* EventTest.razor *@
    <h3>EventTest</h3>
    
    <div>
        <button @onclick="Test">按钮</button>
    </div>
    
    @code {
        [Parameter]
        public EventCallback<MouseEventArgs> Test { get; set; }
    }
    
    @page "/counter"
    @rendermode InteractiveServer
    
    <EventTest Test="Test"/>
    
    @count
    
    @code{
        private int count = 0;
        private void Test(MouseEventArgs args)
    	{
    	    count += 1;
    	}
    }
    

内置的事件参数

对于支持事件参数的DOM事件,在指定事件处理程序时,可以在参数列表中声明事件参数来接收。

下面的例子中,ReportPointerLocation方法使用了 MouseEventArgs 来设置消息文本,以便在用户选择 UI 中的按钮时获取鼠标坐标

  • 示例

    @page "/event-handler"
    
    <PageTitle>Event Handler</PageTitle>
    
    <h1>Event Handler Example</h1>
    
    @for (var i = 0; i < 4; i++)
    {
        <p>
            <button @onclick="ReportPointerLocation">
                Where's my mouse pointer for this button?
            </button>
        </p>
    }
    
    <p>@mousePointerMessage</p>
    
    @code {
        private string? mousePointerMessage;
    
        private void ReportPointerLocation(MouseEventArgs e)
        {
            mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
        }
    }
    

非内置事件参数的参数

有时,可能在执行事件处理程序时,希望传入一些自定义的参数,此时可以在设置事件处理程序时,通过Lambda表达式,再做一层处理,然后将参数传入到真正的事件处理方法上。

  • 示例-lambda表达式

    @page "/counter"
    @rendermode InteractiveServer
    
    <div>
        <button @onclick="@((args)=>Test(args,"如果要传入自定义的参数,可以使用一下Lambda"))">按钮</button>
    </div>
    
    @count
    @message
    
    @code{
        private int count = 0;
        private string message = "";
        private void Test(MouseEventArgs agrs, string param)
        {
            count += 1;
            message = param;
        }
    }
    

三、自定义事件

Blazor 支持自定义事件(这里的自定义事件是在DOM事件的基础上的),在自定义事件中,可以设置自定义的事件参数,借助这些参数,可以将任意数据通过自定义事件传递给 .NET 事件处理程序。

创建JS初始设置项

在wwwroot下添加{ASSEMBLY NAME}.lib.module.js文件

  • 每个事件仅在脚本中调用 registerCustomEventType 一次。

  • BlazorServer.lib.module.js

    export function afterWebStarted(blazor) {
      blazor.registerCustomEventType('custompaste', {
        browserEventName: 'paste',
        createEventArgs: event => {
          return {
            eventTimestamp: new Date(),
            pastedData: event.clipboardData.getData('text')
          };
        }
      });
    }
    

创建C#事件处理类与参数

一般情况下,可以在项目中新建CustomEvents文件夹,在其中创建自定义事件处理类以及自定义事件参数

  • 事件处理类必须使用[EventHandler]特性进行注释,静态的且名为EventHandlers,这样才可以被Razor编译器找到。

  • CustomPasteEventArgs.cs

    [EventHandler("oncustompaste", typeof(CustomPasteEventArgs), 
        enableStopPropagation: true, enablePreventDefault: true)]
    public static class EventHandlers
    {
    }
    
    public class CustomPasteEventArgs : EventArgs
    {
        public DateTime EventTimestamp { get; set; }
        public string? PastedData { get; set; }
    }
    

在组件中使用

  • CustomPasteArguments.razor

    @page "/custom-paste-arguments"
    @rendermode InteractiveServer
    @using BlazorServer.CustomEvents
    
    <label>
        Try pasting into the following text box:
        <input @oncustompaste="HandleCustomPaste"/>
    </label>
    
    <p>
        @message
    </p>
    
    @code {
        private string? message;
    
        private void HandleCustomPaste(CustomPasteEventArgs eventArgs)
        {
            message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, " + $"you pasted: {eventArgs.PastedData}";
        }
    }
    

跨组件公开事件

在项目开发过程中,很多情况下会遇到希望在子组件中触发某个事件时,能够调用到父组件中的处理方法。这里所说的跨组件公开事件,指的是子组件向父组件公开EventCallback组件参数,父组件在使用子组件时,通过组件参数,给子组件设置对应的事件处理方法。

EventCallbackEventCallback<TValue>: 事件回调(事件处理程序),可以在组件中配合[Parameter]定义组件参数暴露给使用者,接收委托作为事件的实际处理方法。

  • HasDelegate:获取当前EventCallback<TValue>对象是否具有委托。

  • InvokeAsync([Object]):调用与此绑定关联的委托,如果需要,可以传入一个object参数给委托。

  • 如果需要给委托传递值,建议优先使用EventCallback<TValue>而不是EventCallback,有利于VS的错误反馈,当然如果不需要传递任何值,直接用EventCallback就可以了 。

  • EventCallback调用的委托后会自动调用StateHasChanged()方法进行重新渲染,没必要手动调用。

  • Child.razor

    <h3>Child Component</h3>
    
    <button @onclick="TriggerEvent">Click Me</button>
    
    @code {
        [Parameter]
        public EventCallback<string> OnClickCallback { get; set; }
    
        private async Task TriggerEvent()
        {
            await OnClickCallback.InvokeAsync("Blaze It!");
        }
    }
    
  • ParentChild.razor

    @page "/parent-child"
    @rendermode InteractiveServer
    
    <PageTitle>Parent Child</PageTitle>
    
    <h1>Parent Child Example</h1>
    
    <div>
        <Child OnClickCallback="(value) => { message1 = value; }" />
        @message1
    </div>
    
    <div>
        <Child OnClickCallback="async (value) => {
    					                    await Task.Delay(2000);
    					                    message2 = value;
    				                    }"/>
        @message2
    </div>
    
    @code {
        private string message1 = string.Empty;
        private string message2 = string.Empty;
    }
    

其他操作

一、阻止默认操作

一般情况下,DOM事件都有自己的默认行为。例如,当我们将焦点定位在某个文本框上并按下某个按键时,浏览器通常在该文本框中输入该键的字符。如果我们不希望件字符直接输入到文本框中,可以通过使用Razor属性指令@on{DOM EVENT}:preventDefault来阻止默认行为。

  • 示例

    @page "/event-handler"
    @rendermode InteractiveServer
    
    <PageTitle>Event Handler</PageTitle>
    
    <h1>Event Handler Example</h1>
    
    <p>For this example, give the <code><input></code> focus.</p>
    
    <p>
        <label>
            Count of '+' key presses:
            <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
        </label>
    </p>
    
    @code {
        private int count = 0;
    
        private void KeyHandler(KeyboardEventArgs e)
        {
            if (e.Key == "+")
            {
                count++;
            }
        }
    }
    

二、聚焦元素

可以调用元素对象的FocusAsync方法来将元素作为焦点。

  • 示例

    <p>
        <label>
            Input: 
            <input @ref="exampleInput" />
        </label>
        
    </p>
    
    <button @onclick="ChangeFocus">
        Focus the Input Element
    </button>
    
    @code {
        private ElementReference exampleInput;
    
        private async Task ChangeFocus()
        {
            await exampleInput.FocusAsync();
        }
    }
    

三、停止事件传播

使用 @on{DOM EVENT}:stopPropagation 指令属性来停止事件在 Blazor 范围内传播。 {DOM EVENT} 是 DOM 事件的占位符。

  • stopPropagation 指令属性的效果仅限于 Blazor 范围,不会扩展到 HTML DOM。 事件必须传播到 HTML DOM 根目录,然后 Blazor 才能对其进行操作。

  • 示例

    @page "/event-handler-7"
    
    <PageTitle>Event Handler 7</PageTitle>
    
    <h1>Event Handler Example 7</h1>
    
    <div>
        <b>stopPropagation</b>: @stopPropagation
    </div>
    
    <div>
        <button @onclick="StopPropagation">
            Stop Propagation (stopPropagation = true)
        </button>
        <button @onclick="EnablePropagation">
            Enable Propagation (stopPropagation = false)
        </button>
    </div>
    
    <div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
        <h3>Parent div</h3>
    
        <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
            Child div that never stops propagation to the parent div when 
            selected.
        </div>
    
        <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
                @onclick:stopPropagation="stopPropagation">
            Child div that stops propagation when selected if 
            <b>stopPropagation</b> is <b>true</b>.
        </div>
    </div>
    
    <p>
        @message
    </p>
    
    @code {
        private bool stopPropagation = false;
        private string? message;
    
        private void StopPropagation() => stopPropagation = true;
    
        private void EnablePropagation() => stopPropagation = false;
    
        private void OnSelectParentDiv() =>
            message = $"The parent div was selected. {DateTime.Now}";
    
        private void OnSelectChildDiv() =>
            message = $"The child div was selected. {DateTime.Now}";
    }
    

相关文章:

  • 设计模式 之 工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)(C++)
  • centos服务器巡检脚本
  • Windows逆向工程入门之字符串类型解析与拓展
  • C语言预处理学习笔记
  • Docker Desktop 入门教学
  • python组备赛笔记(基础篇)
  • 从零到一:构建现代 React 应用的完整指南
  • Netty入门详解
  • halcon机器视觉深度学习对象检测,物体检测
  • 自学FOC系列分享--SVPWM和clark 逆变换及代码实战
  • docker从容器中cp到本地、cp本地到容器
  • LabVIEW开发中的电机控制与相机像素差
  • Visual Studio中打开多个项目
  • 【微中子代理踩坑-前端node-sass安装失败】
  • 敏捷开发07:敏捷项目可视化管理-ScrumBoard(Scrum板)使用介绍
  • rust 实例化动态对象
  • IC卡、M1卡及各类卡的原理使用说明
  • 以太网的MAC(介质访问控制)详解
  • 前端知识点---vue的声明周期(vue)
  • RAGFLOW使用flask转发的open ai接口
  • 最大规模的陈逸飞大展启幕:回望他,回望一个时代
  • 证券时报:落实“非禁即入” ,让创新活力充分涌流
  • “茉上茶田”傍大牌诱导加盟续:违规从事特许经营被罚没670余万元
  • “全国十大考古”揭晓:盘龙城遗址、周原遗址等入选
  • 小鹏机器人IRON亮相上海车展,何小鹏:相信更多人形机器人会现身车展
  • 秭归“橘颂”:屈原故里打造脐橙全产业链,创造12个亿元村,运输用上无人机