You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:09:05