Blazor Server应用下指定操作触发输入框与标签切换的实现咨询
Blazor Server 可编辑标签组件实现方案
前置说明
通过状态变量控制「标签展示/输入框编辑」两种视图的切换,分别绑定对应事件覆盖4种退出编辑触发逻辑。
完整代码示例
1. 组件代码(EditableLabel.razor)
@inject IJSRuntime JSRuntime @implements IAsyncDisposable <!-- 非编辑状态显示标签 --> @if (!isEditing) { <span class="editable-label" @onclick="StartEditing">@displayText</span> } <!-- 编辑状态显示输入框结构 --> else { <div class="row" id="@containerId"> <div class="col-md-5 mx-auto"> <div class="input-group"> <input @ref="inputRef" class="form-control border-end-0 border rounded-pill" type="text" @bind="inputValue" @bind:event="oninput" @onblur="FinishEditing" @onkeydown="HandleKeyDown" id="example-text-input"> <span> <button class="btn btn-outline-secondary bg-white border-bottom-0 border rounded-pill ms-n5" type="button" @onclick="FinishEditing"> <i class="fas fa-arrow-alt-circle-right"></i> </button> </span> </div> </div> </div> } @code { [Parameter, EditorRequired] public string? InitialText { get; set; } private bool isEditing; private string? inputValue; private string? displayText; private ElementReference inputRef; private string containerId = $"editable_{Guid.NewGuid():N}"; private DotNetObjectReference<EditableLabel>? dotnetRef; protected override void OnInitialized() { displayText = InitialText; inputValue = InitialText; dotnetRef = DotNetObjectReference.Create(this); } // 进入编辑状态,自动聚焦输入框+注册全局点击监听 private async Task StartEditing() { isEditing = true; await Task.Yield(); await inputRef.FocusAsync(); await JSRuntime.InvokeVoidAsync("EditableLabel.addGlobalClickListener", containerId, dotnetRef); } // 退出编辑逻辑,同步输入值到标签+移除全局监听 private async Task FinishEditing() { if (!isEditing) return; isEditing = false; displayText = inputValue; await JSRuntime.InvokeVoidAsync("EditableLabel.removeGlobalClickListener", containerId); } // 处理键盘事件,按下回车触发退出编辑 private async Task HandleKeyDown(KeyboardEventArgs e) { if (e.Key is "Enter") { await FinishEditing(); } } // 供JS调用的外部点击触发方法 [JSInvokable] public async Task OnOutsideClick() { await FinishEditing(); } // 释放资源避免内存泄漏 public async ValueTask DisposeAsync() { if (dotnetRef != null) { await JSRuntime.InvokeVoidAsync("EditableLabel.removeGlobalClickListener", containerId); dotnetRef.Dispose(); } } }
2. 配套JS代码(wwwroot/js/editableLabel.js)
在App.razor中引入该JS文件,代码内容如下:
window.EditableLabel = { // 注册全局点击监听 addGlobalClickListener: function (containerId, dotnetRef) { const handler = function (e) { const container = document.getElementById(containerId); if (container && !container.contains(e.target)) { dotnetRef.invokeMethodAsync('OnOutsideClick'); document.removeEventListener('click', handler); } }; // 存储handler到元素上方便后续移除 document.getElementById(containerId)._clickHandler = handler; document.addEventListener('click', handler); }, // 移除全局点击监听 removeGlobalClickListener: function (containerId) { const container = document.getElementById(containerId); if (container && container._clickHandler) { document.removeEventListener('click', container._clickHandler); delete container._clickHandler; } } }
触发逻辑对应说明
- 点击箭头按钮:按钮绑定
@onclick="FinishEditing"直接触发退出编辑 - 按下Tab键失焦:输入框绑定
@onblur事件,失焦时自动触发退出 - 按下回车键:输入框绑定
@onkeydown事件,判断按下键为Enter时触发退出 - 点击页面其他区域:通过JS全局监听点击事件,判断点击目标不在组件内部时触发JS互操作调用退出逻辑
内容的提问来源于stack exchange,提问作者Baba
相关产品推荐
相关产品推荐

