Blazor Server(.NET 7)下拉框控制输入框显隐:JS/jQuery或C#方案
Blazor Server(.NET Core 7)下拉框联动显示/隐藏输入框问题解决
问题背景
开发基于.NET Core 7的Blazor Server应用时,在serverNames.Razor组件中尝试用jQuery实现下拉框选择后显示/隐藏输入框,出现Cannot read properties of null (reading 'removeChild')错误。
组件HTML结构
<div class="col-md-4 col-lg-3"> <div class="form-group" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="example-text-input" class="col-3 col-form-label">SearchBy</label> <select id="ddlOptionSearch" class="form-select"> <option value="0">--Select--</option> <option value="1">Server Name</option> <option value="2">Server Type</option> </select> </div> </div> <div class="col-md-3 col-lg-2"> <div id="dvSearch" style="display: none"> Server Number: <input type="text" class="form-control" id="txtServerName" /> </div> </div>
所用jQuery脚本
<script type="text/javascript"> $(function () { $("#ddlOptionSearch").change(function () { if ($(this).val() == "Server Name") { console.log("server name selected"); $("#dvSearch").show(); } else { $("#dvSearch").hide(); } }); }); </script>
报错信息
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'removeChild') at j (blazor.server.js:1:17509) at blazor.server.js:1:20768 at se.updateComponent (blazor.server.js:1:20793) at blazor.server.js:1:118191 at Hn.processBatch (blazor.server.js:1:118563) at Ft.<anonymous> (blazor.server.js:1:133366) at Ft._invokeClientMethod (blazor.server.js:1:75072) at Ft._processIncomingData (blazor.server.js:1:72696) at Ft.connection.onreceive (blazor.server.js:1:67009) at i.onmessage (blazor.server.js:1:51322) blazor.server.js:1 [2023-03-13T13:25:21.637Z] Error: System.AggregateException: One or more errors occurred. (TypeError: Cannot read properties of null (reading 'removeChild')) ---> System.InvalidOperationException: TypeError: Cannot read properties of null (reading 'removeChild') at Microsoft.AspNetCore.Components.RenderTree.Renderer.InvokeRenderCompletedCallsAfterUpdateDisplayTask(Task updateDisplayTask, Int32[] updatedComponents) --- End of inner exception stack trace ---
解决方案
原因分析
- DOM渲染冲突:Blazor Server通过SignalR双向绑定管理DOM,组件会频繁重新渲染,jQuery直接操作DOM会和Blazor的渲染机制冲突——当Blazor重新渲染时,jQuery修改过的DOM元素可能已被销毁,导致找不到元素抛出错误。
- 逻辑错误:下拉框选项的
value是数字字符串("1"/"2"),但脚本中判断的是等于文本"Server Name",永远不会触发显示逻辑。
方案一:Blazor原生C#实现(推荐)
利用Blazor的数据绑定和条件渲染,完全由框架管理DOM,避免冲突:
<div class="col-md-4 col-lg-3"> <div class="form-group" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label class="col-3 col-form-label">SearchBy</label> <select @bind="SelectedSearchOption" class="form-select"> <option value="0">--Select--</option> <option value="1">Server Name</option> <option value="2">Server Type</option> </select> </div> </div> <div class="col-md-3 col-lg-2"> @if (SelectedSearchOption == 1) { <div> Server Number: <input type="text" class="form-control" @bind="ServerName" /> </div> } </div> @code { // 绑定下拉框选中值 private int SelectedSearchOption { get; set; } = 0; // 绑定输入框内容 private string ServerName { get; set; } = string.Empty; }
说明
- 使用
@bind将下拉框选中值绑定到C#属性SelectedSearchOption - 通过
@if条件渲染控制输入框的显示/隐藏,完全符合Blazor的渲染机制 - 数据直接绑定到C#属性,方便后续业务逻辑调用
方案二:修正后的jQuery实现(不推荐,仅作兼容参考)
若必须使用jQuery,需解决DOM渲染时机和逻辑错误问题:
- 组件代码:通过JSInterop在组件渲染完成后绑定事件
<div class="col-md-4 col-lg-3"> <div class="form-group" style="display:flex; flex-direction: row; justify-content: center; align-items: center"> <label for="example-text-input" class="col-3 col-form-label">SearchBy</label> <select id="ddlOptionSearch" class="form-select"> <option value="0">--Select--</option> <option value="1">Server Name</option> <option value="2">Server Type</option> </select> </div> </div> <div class="col-md-3 col-lg-2"> <div id="dvSearch" style="display: none"> Server Number: <input type="text" class="form-control" id="txtServerName" /> </div> </div> @code { [Inject] private IJSRuntime JSRuntime { get; set; } protected override async Task OnAfterRenderAsync(bool firstRender) { // 仅在首次渲染完成后绑定事件 if (firstRender) { await JSRuntime.InvokeVoidAsync("initSearchDropdown"); } } }
- 布局页脚本:在
_Layout.cshtml中添加脚本(Blazor Server无index.html,布局页负责引入全局资源)
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script> function initSearchDropdown() { // 先解绑再绑定,避免重复注册事件 $("#ddlOptionSearch").off("change").on("change", function () { // 匹配选项的value值"1",而非文本 if ($(this).val() === "1") { $("#dvSearch").show(); } else { $("#dvSearch").hide(); } }); } </script>
说明
- 在
OnAfterRenderAsync中调用JS方法,确保DOM已渲染完成 - 使用
.off("change").on("change")避免重复绑定事件 - 修正判断条件为匹配选项的
value值,而非显示文本
内容的提问来源于stack exchange,提问作者ahmed abdelaziz
相关产品推荐
相关产品推荐

