ASP.NET Core Blazor简介和快速入门二(组件基础之事件处理)

举报
码农刚子 发表于 2025/11/15 23:47:56 2025/11/15
【摘要】 大家好,我是码农刚子。上一章介绍了Blazor组件的数据绑定。接下来我们继续了解Blazor 组件事件处理相关的基础知识,希望对你有所帮助。1、事件处理1. 基本事件处理1.1 单击事件<!-- ClickEvents.razor --><div class="click-demo"> <h3>单击事件示例</h3> <!-- 基本点击事件 --> <button ...

大家好,我是码农刚子。上一章介绍了Blazor组件的数据绑定。接下来我们继续了解Blazor 组件事件处理相关的基础知识,希望对你有所帮助。

1、事件处理

1. 基本事件处理

1.1 单击事件

<!-- ClickEvents.razor -->
<div class="click-demo">
    <h3>单击事件示例</h3>
    
    <!-- 基本点击事件 -->
    <button @onclick="HandleClick" class="btn btn-primary">
        点击我
    </button>
    <!-- 带参数的事件处理 -->
    <div class="button-group">
        <button @onclick="() => HandleButtonClick(1)" class="btn btn-secondary">按钮 1</button>
        <button @onclick="() => HandleButtonClick(2)" class="btn btn-secondary">按钮 2</button>
        <button @onclick="() => HandleButtonClick(3)" class="btn btn-secondary">按钮 3</button>
    </div>
    <!-- 显示点击结果 -->
    <div class="result">
        <p>最后点击的按钮: @lastClickedButton</p>
        <p>点击次数: @clickCount</p>
    </div>
</div>
@code {
    private int lastClickedButton = 0;
    private int clickCount = 0;
    private void HandleClick()
    {
        clickCount++;
        Console.WriteLine("按钮被点击了!");
    }
    private void HandleButtonClick(int buttonNumber)
    {
        lastClickedButton = buttonNumber;
        clickCount++;
        StateHasChanged();
    }
}

1.2 异步事件处理

<!-- AsyncEvents.razor -->
<div class="async-demo">
    <h3>异步事件处理</h3>
    
    <button @onclick="HandleAsyncClick" class="btn btn-primary" disabled="@isLoading">
        @if (isLoading)
        {
            <span>加载中...</span>
        }
        else
        {
            <span>模拟异步操作</span>
        }
    </button>
    <div class="result">
        <p>操作结果: @operationResult</p>
        <p>耗时: @elapsedTime 毫秒</p>
    </div>
</div>
@code {
    private bool isLoading = false;
    private string operationResult = string.Empty;
    private long elapsedTime = 0;
    private async Task HandleAsyncClick()
    {
        isLoading = true;
        operationResult = "操作开始...";
        
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        // 模拟异步操作
        await Task.Delay(2000);
        
        stopwatch.Stop();
        elapsedTime = stopwatch.ElapsedMilliseconds;
        
        operationResult = $"操作完成!数据已保存。";
        isLoading = false;
        
        StateHasChanged();
    }
}

2. 表单事件处理

2.1 输入事件

<!-- FormEvents.razor -->
<div class="form-events">
    <h3>表单事件处理</h3>
    
    <div class="form-group">
        <label>输入文本:</label>
        <input @oninput="HandleInput" 
               @onchange="HandleChange"
               class="form-control" 
               placeholder="输入内容..." />
        <small>实时输入: @inputValue | 变化事件: @changeValue</small>
    </div>
    <div class="form-group">
        <label>选择选项:</label>
        <select @onchange="HandleSelectChange" class="form-control">
            <option value="">请选择</option>
            <option value="option1">选项一</option>
            <option value="option2">选项二</option>
            <option value="option3">选项三</option>
        </select>
        <small>选择的值: @selectedValue</small>
    </div>
    <div class="form-group">
        <label>
            <input type="checkbox" @onchange="HandleCheckboxChange" />
            同意条款
        </label>
        <small>状态: @(isChecked ? "已选中" : "未选中")</small>
    </div>
    <!-- 表单提交 -->
    <form @onsubmit="HandleSubmit" @onvalidSubmit="HandleValidSubmit">
        <div class="form-group">
            <label>用户名:</label>
            <input @bind="user.Username" class="form-control" required />
        </div>
        
        <div class="form-group">
            <label>邮箱:</label>
            <input @bind="user.Email" type="email" class="form-control" required />
        </div>
        
        <button type="submit" class="btn btn-success">提交表单</button>
    </form>
    <div class="form-result">
        <h4>表单数据:</h4>
        <pre>@System.Text.Json.JsonSerializer.Serialize(user, new System.Text.Json.JsonSerializerOptions { WriteIndented = true })</pre>
        <p>提交状态: @submitStatus</p>
    </div>
</div>
@code {
    private string inputValue = string.Empty;
    private string changeValue = string.Empty;
    private string selectedValue = string.Empty;
    private bool isChecked = false;
    private string submitStatus = "未提交";
    
    private User user = new User();
    private void HandleInput(ChangeEventArgs e)
    {
        inputValue = e.Value?.ToString() ?? string.Empty;
    }
    private void HandleChange(ChangeEventArgs e)
    {
        changeValue = e.Value?.ToString() ?? string.Empty;
    }
    private void HandleSelectChange(ChangeEventArgs e)
    {
        selectedValue = e.Value?.ToString() ?? string.Empty;
    }
    private void HandleCheckboxChange(ChangeEventArgs e)
    {
        isChecked = (bool)(e.Value ?? false);
    }
    private void HandleSubmit()
    {
        submitStatus = "表单提交(可能有验证错误)";
    }
    private void HandleValidSubmit()
    {
        submitStatus = $"表单验证通过!数据已保存 - {DateTime.Now:HH:mm:ss}";
        // 这里可以调用API保存数据
    }
    class User
    {
        public string Username { get; set; } = string.Empty;
        public string Email { get; set; } = string.Empty;
    }
}

3. 鼠标和键盘事件

3.1 鼠标事件

<!-- MouseEvents.razor -->
<div class="mouse-events">
    <h3>鼠标事件</h3>
    
    <div class="interactive-area"
         @onmousedown="HandleMouseDown"
         @onmouseup="HandleMouseUp"
         @onmousemove="HandleMouseMove"
         @onmouseover="HandleMouseOver"
         @onmouseout="HandleMouseOut"
         @onclick="HandleAreaClick"
         @ondblclick="HandleDoubleClick"
         style="width: 300px; height: 200px; border: 2px solid #007bff; padding: 20px; margin: 10px 0;">
        鼠标交互区域
    </div>
    <div class="event-log">
        <h4>事件日志:</h4>
        <ul>
            @foreach (var log in eventLogs.TakeLast(10).Reverse())
            {
                <li>@log</li>
            }
        </ul>
    </div>
    <div class="mouse-info">
        <p>鼠标位置: (@mouseX, @mouseY)</p>
        <p>按钮状态: @(isMouseDown ? "按下" : "释放")</p>
        <p>悬停状态: @(isMouseOver ? "在区域内" : "在区域外")</p>
    </div>
</div>
@code {
    private double mouseX = 0;
    private double mouseY = 0;
    private bool isMouseDown = false;
    private bool isMouseOver = false;
    private List<string> eventLogs = new List<string>();
    private void LogEvent(string eventName)
    {
        eventLogs.Add($"{DateTime.Now:HH:mm:ss.fff} - {eventName}");
        StateHasChanged();
    }
    private void HandleMouseDown(MouseEventArgs e)
    {
        isMouseDown = true;
        LogEvent($"MouseDown - 按钮: {e.Button}, 位置: ({e.ClientX}, {e.ClientY})");
    }
    private void HandleMouseUp(MouseEventArgs e)
    {
        isMouseDown = false;
        LogEvent($"MouseUp - 按钮: {e.Button}, 位置: ({e.ClientX}, {e.ClientY})");
    }
    private void HandleMouseMove(MouseEventArgs e)
    {
        mouseX = e.ClientX;
        mouseY = e.ClientY;
        // 注意:频繁触发,生产环境需要节流
        // LogEvent($"MouseMove - 位置: ({e.ClientX}, {e.ClientY})");
    }
    private void HandleMouseOver(MouseEventArgs e)
    {
        isMouseOver = true;
        LogEvent("MouseOver");
    }
    private void HandleMouseOut(MouseEventArgs e)
    {
        isMouseOver = false;
        LogEvent("MouseOut");
    }
    private void HandleAreaClick(MouseEventArgs e)
    {
        LogEvent($"Click - 按钮: {e.Button}");
    }
    private void HandleDoubleClick(MouseEventArgs e)
    {
        LogEvent($"DoubleClick - 按钮: {e.Button}");
    }
}

3.2 键盘事件

<!-- KeyboardEvents.razor -->
<div class="keyboard-events">
    <h3>键盘事件</h3>
    
    <div class="input-area">
        <input @onkeydown="HandleKeyDown"
               @onkeyup="HandleKeyUp"
               @onkeypress="HandleKeyPress"
               class="form-control"
               placeholder="在这里输入并观察键盘事件..." />
    </div>
    <div class="event-log">
        <h4>键盘事件日志:</h4>
        <ul>
            @foreach (var log in keyEventLogs.TakeLast(10).Reverse())
            {
                <li>@log</li>
            }
        </ul>
    </div>
    <div class="key-info">
        <p>最后按下的键: @lastKey</p>
        <p>Ctrl 按下: @(isCtrlPressed ? "是" : "否")</p>
        <p>Shift 按下: @(isShiftPressed ? "是" : "否")</p>
        <p>Alt 按下: @(isAltPressed ? "是" : "否")</p>
    </div>
</div>
@code {
    private string lastKey = "无";
    private bool isCtrlPressed = false;
    private bool isShiftPressed = false;
    private bool isAltPressed = false;
    private List<string> keyEventLogs = new List<string>();
    private void LogKeyEvent(string eventName, KeyboardEventArgs e)
    {
        var log = $"{DateTime.Now:HH:mm:ss.fff} - {eventName}: Key='{e.Key}', Code='{e.Code}'";
        if (e.CtrlKey) log += " [Ctrl]";
        if (e.ShiftKey) log += " [Shift]";
        if (e.AltKey) log += " [Alt]";
        
        keyEventLogs.Add(log);
        StateHasChanged();
    }
    private void HandleKeyDown(KeyboardEventArgs e)
    {
        lastKey = e.Key;
        isCtrlPressed = e.CtrlKey;
        isShiftPressed = e.ShiftKey;
        isAltPressed = e.AltKey;
        
        LogKeyEvent("KeyDown", e);
        // 快捷键处理示例
        if (e.CtrlKey && e.Key == "s")
        {
            e.PreventDefault(); // 阻止浏览器默认保存行为
            LogKeyEvent("快捷键: Ctrl+S", e);
        }
    }
    private void HandleKeyUp(KeyboardEventArgs e)
    {
        isCtrlPressed = e.CtrlKey;
        isShiftPressed = e.ShiftKey;
        isAltPressed = e.AltKey;
        
        LogKeyEvent("KeyUp", e);
    }
    private void HandleKeyPress(KeyboardEventArgs e)
    {
        LogKeyEvent("KeyPress", e);
    }
}

4. 焦点和剪贴板事件

<!-- FocusClipboardEvents.razor -->
<div class="focus-clipboard">
    <h3>焦点和剪贴板事件</h3>
    
    <div class="form-group">
        <label>焦点测试输入框:</label>
        <input @onfocus="HandleFocus"
               @onblur="HandleBlur"
               class="form-control"
               placeholder="点击获取焦点,点击别处失去焦点" />
    </div>
    <div class="form-group">
        <label>复制粘贴测试:</label>
        <textarea @oncopy="HandleCopy"
                  @oncut="HandleCut"
                  @onpaste="HandlePaste"
                  class="form-control"
                  rows="3"
                  placeholder="在这里测试复制、剪切、粘贴操作">这是一些测试文本</textarea>
    </div>
    <div class="event-log">
        <h4>事件状态:</h4>
        <p>焦点状态: <span class="@(hasFocus ? "text-success" : "text-danger")">@(hasFocus ? "有焦点" : "无焦点")</span></p>
        <p>最后操作: @lastOperation</p>
        <p>剪贴板内容: @clipboardContent</p>
    </div>
</div>
@code {
    private bool hasFocus = false;
    private string lastOperation = "无";
    private string clipboardContent = "无";
    private void HandleFocus(FocusEventArgs e)
    {
        hasFocus = true;
        lastOperation = "获得焦点";
        StateHasChanged();
    }
    private void HandleBlur(FocusEventArgs e)
    {
        hasFocus = false;
        lastOperation = "失去焦点";
        StateHasChanged();
    }
    private void HandleCopy(ClipboardEventArgs e)
    {
        lastOperation = "复制操作";
        clipboardContent = "复制的内容无法直接获取(安全限制)";
        StateHasChanged();
    }
    private void HandleCut(ClipboardEventArgs e)
    {
        lastOperation = "剪切操作";
        clipboardContent = "剪切的内容无法直接获取(安全限制)";
        StateHasChanged();
    }
    private void HandlePaste(ClipboardEventArgs e)
    {
        lastOperation = "粘贴操作";
        clipboardContent = "粘贴的内容无法直接获取(安全限制)";
        StateHasChanged();
    }
}

5. 自定义事件处理

5.1 事件参数封装

<!-- CustomEventHandling.razor -->
<div class="custom-events">
    <h3>自定义事件处理</h3>
    
    <!-- 事件冒泡和阻止默认行为 -->
    <div @onclick="HandleParentClick" style="padding: 20px; border: 2px solid red;">
        <p>父级区域(点击会触发)</p>
        <button @onclick="HandleChildClick" 
                @onclick:stopPropagation
                class="btn btn-primary">
            子按钮(点击不会冒泡)
        </button>
        
        <button @onclick="HandleChildClickWithPrevent" 
                @onclick:preventDefault
                class="btn btn-secondary">
            阻止默认行为的按钮
        </button>
    </div>
    <!-- 自定义事件处理逻辑 -->
    <div class="custom-actions">
        <h4>自定义操作:</h4>
        <button @onclick="HandleCustomAction1" class="btn btn-info">操作1</button>
        <button @onclick="HandleCustomAction2" class="btn btn-info">操作2</button>
        <button @onclick="async () => await HandleCustomAsyncAction()" class="btn btn-info">异步操作</button>
    </div>
    <div class="action-log">
        <h4>操作日志:</h4>
        <ul>
            @foreach (var log in actionLogs.TakeLast(5).Reverse())
            {
                <li>@log</li>
            }
        </ul>
    </div>
</div>
@code {
    private List<string> actionLogs = new List<string>();
    private void LogAction(string action)
    {
        actionLogs.Add($"{DateTime.Now:HH:mm:ss} - {action}");
        StateHasChanged();
    }
    private void HandleParentClick()
    {
        LogAction("父级区域被点击");
    }
    private void HandleChildClick()
    {
        LogAction("子按钮被点击(事件不会冒泡)");
    }
    private void HandleChildClickWithPrevent()
    {
        LogAction("阻止默认行为的按钮被点击");
    }
    private void HandleCustomAction1()
    {
        LogAction("执行自定义操作1");
        // 自定义业务逻辑
    }
    private void HandleCustomAction2(MouseEventArgs e)
    {
        LogAction($"执行自定义操作2 - 点击位置: ({e.ClientX}, {e.ClientY})");
        // 自定义业务逻辑
    }
    private async Task HandleCustomAsyncAction()
    {
        LogAction("开始异步操作");
        await Task.Delay(1000);
        LogAction("异步操作完成");
    }
}

6. 事件处理最佳实践

6.1 性能优化

<!-- OptimizedEvents.razor -->
<div class="optimized-events">
    <h3>事件处理性能优化</h3>
    <!-- 避免内联Lambda表达式(可能引起不必要的重渲染) -->
    @foreach (var item in items)
    {
        <div class="item" @key="item.Id">
            <span>@item.Name</span>
            <!-- 好的做法:使用方法引用 -->
            <button @onclick="() => DeleteItem(item.Id)" class="btn btn-sm btn-danger">删除</button>
        </div>
    }
    <!-- 大量事件考虑使用事件委托 -->
    <div class="large-list">
        @foreach (var item in largeList)
        {
            <div class="list-item" data-id="@item.Id" data-name="@item.Name" @onclick="(e) => HandleListItemClick(e, item.Id)">
                @item.Name
            </div>
        }
    </div>
    <div class="action-log">
        <h4>操作日志:</h4>
        <ul>
            @foreach (var log in actionLogs.TakeLast(5).Reverse())
            {
                <li>@log</li>
            }
        </ul>
    </div>
</div>
@code {
    private List<Item> items = new List<Item>
    {
        new Item { Id = 1, Name = "项目1" },
        new Item { Id = 2, Name = "项目2" },
        new Item { Id = 3, Name = "项目3" }
    };
    private List<Item> largeList = Enumerable.Range(1, 100)
        .Select(i => new Item { Id = i, Name = $"项目{i}" })
        .ToList();
    private List<string> actionLogs = new List<string>();
    private void DeleteItem(int id)
    {
        items.RemoveAll(i => i.Id == id);
        LogAction($"删除了项目 {id}");
    }
    private void HandleListItemClick(MouseEventArgs e, int itemId)
    {
        // 通过参数 itemId 就知道是哪个按钮被点击了
        Console.WriteLine($"Clicked item ID: {itemId}");
    }
    // 添加 LogAction 方法
    private void LogAction(string action)
    {
        actionLogs.Add($"{DateTime.Now:HH:mm:ss} - {action}");
        StateHasChanged();
    }
    class Item
    {
        public int Id { get; set; }
        public string Name { get; set; } = string.Empty;
    }
}

7. 常用事件总结

事件类型

指令

事件参数

说明

点击事件

@onclick

MouseEventArgs

鼠标点击

双击事件

@ondblclick

MouseEventArgs

鼠标双击

鼠标移动

@onmousemove

MouseEventArgs

鼠标移动

鼠标按下

@onmousedown

MouseEventArgs

鼠标按下

鼠标释放

@onmouseup

MouseEventArgs

鼠标释放

键盘按下

@onkeydown

KeyboardEventArgs

键盘按下

键盘释放

@onkeyup

KeyboardEventArgs

键盘释放

输入事件

@oninput

ChangeEventArgs

输入时触发

变化事件

@onchange

ChangeEventArgs

值变化时触发

获得焦点

@onfocus

FocusEventArgs

元素获得焦点

失去焦点

@onblur

FocusEventArgs

元素失去焦点

表单提交

@onsubmit

EventArgs

表单提交

以上就是关于《ASP.NET Core Blazor简介和快速入门二(组件基础之数据绑定)》的全部内容,希望你有所收获。关注、点赞,持续分享

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。