Blazor:EditForm.Model变更后如何保留原输入框的焦点状态
通用解决方案:自定义保留焦点的EditForm组件
该方案无需修改现有表单内的输入组件代码,仅需替换原有EditForm标签即可实现焦点自动保留,适配所有Blazor原生输入组件及自定义输入组件。
步骤1:添加全局JS辅助函数
将以下代码添加到项目的入口HTML文件中(Blazor WebAssembly项目为wwwroot/index.html,Blazor Server项目为Pages/_Layout.cshtml/Pages/_Host.cshtml):
window.FocusPreserver = { // 保存表单内当前聚焦元素的唯一选择器 saveActiveElement: function (formElement) { const activeEl = document.activeElement; // 仅当活跃元素属于当前表单时才记录 if (!activeEl || !formElement.contains(activeEl)) return null; if (activeEl.id) return `#${activeEl.id}`; if (activeEl.name) return `${activeEl.tagName}[name="${activeEl.name}"]`; // 无id/name时用标签名+同级索引匹配 const sameTagSiblings = Array.from(formElement.querySelectorAll(activeEl.tagName)); const elIndex = sameTagSiblings.indexOf(activeEl); return `${activeEl.tagName}:nth-of-type(${elIndex + 1})`; }, // 根据保存的选择器恢复焦点 restoreFocus: function (formElement, selector) { if (!selector) return; const targetEl = formElement.querySelector(selector); targetEl?.focus(); } };
步骤2:实现自定义EditForm组件
在项目中新建FocusPreservingEditForm.cs类,继承原生EditForm:
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; using Microsoft.JSInterop; public class FocusPreservingEditForm : EditForm { [Inject] private IJSRuntime JSRuntime { get; set; } private ElementReference _formDomRef; private string _savedActiveElSelector; protected override async Task OnParametersSetAsync() { // 检测到Model变更、即将触发重渲染前,先保存当前焦点 if (Model != null && PreviousModel != null && !Model.Equals(PreviousModel)) { _savedActiveElSelector = await JSRuntime.InvokeAsync<string>( "FocusPreserver.saveActiveElement", _formDomRef ); } await base.OnParametersSetAsync(); } protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); // 重渲染完成后恢复焦点 if (!string.IsNullOrEmpty(_savedActiveElSelector)) { await JSRuntime.InvokeVoidAsync( "FocusPreserver.restoreFocus", _formDomRef, _savedActiveElSelector ); _savedActiveElSelector = null; } } protected override void BuildRenderTree(RenderTreeBuilder builder) { builder.OpenElement(0, "form"); builder.AddMultipleAttributes(1, AdditionalAttributes); // 捕获表单的DOM引用 builder.AddElementReferenceCapture(2, domRef => _formDomRef = domRef); builder.AddContent(3, ChildContent); builder.CloseElement(); } }
步骤3:替换原有EditForm
直接将项目中所有表单的<EditForm>标签替换为<FocusPreservingEditForm>即可,其余代码无需修改:
<FocusPreservingEditForm Model="model"> <!-- 原有输入组件完全不用修改 --> <InputText @bind-Value="model.Name" /> ...数十个其他输入组件 </FocusPreservingEditForm>
适配说明
- 若表单内输入组件为动态生成、重渲染后顺序会发生变化,只需给每个输入组件加唯一的
id或name属性,即可保证选择器精准匹配 - 若你的Model为引用类型且重写了
Equals方法,可自行调整OnParametersSetAsync中的Model变更判断逻辑,适配业务需求 - 该组件完全兼容原生
EditForm的所有参数、验证逻辑及用法
内容的提问来源于stack exchange,提问作者Liero
相关产品推荐
相关产品推荐

