ASP.NET Core MVC中jsTree联动产品表格更新问题求助
解决方案
一、控制器Node方法的返回方案
你有两种实用选择,根据前端实现偏好来选:
1. 返回JSON格式的产品数据
适合前端自行拼接表格DOM的场景,控制器查询数据后序列化为JSON返回:
public IActionResult Node(int categoryId) { // 用EF Core筛选对应分类的产品,按需返回表格所需字段 var products = _context.Products .Where(p => p.CategoryId == categoryId) .Select(p => new { Id = p.Id, ProductName = p.ProductName, Price = p.Price.ToString("C"), Description = p.Description }) .ToList(); return Json(products); }
如果需要支持分页、排序,也可以返回包含分页信息的复合对象(比如{ Total: totalCount, Data: products })。
2. 返回渲染好的表格部分视图
不想前端拼接HTML的话,让控制器返回预渲染的表格片段:
首先创建部分视图_ProductTable.cshtml,传入List<Product>模型:
<table class="table table-striped"> <thead> <tr> <th>ID</th> <th>产品名称</th> <th>价格</th> <th>描述</th> </tr> </thead> <tbody> @foreach (var product in Model) { <tr> <td>@product.Id</td> <td>@product.ProductName</td> <td>@product.Price.ToString("C")</td> <td>@product.Description</td> </tr> } </tbody> </table>
然后控制器方法返回该视图(建议用异步查询优化性能):
public async Task<IActionResult> Node(int categoryId) { var products = await _context.Products .Where(p => p.CategoryId == categoryId) .ToListAsync(); return PartialView("_ProductTable", products); }
二、前端实现节点切换时的表格更新
结合jsTree的changed事件,发送AJAX请求并更新右侧内容:
1. 对应JSON返回的前端逻辑
先在页面右侧添加表格容器:
<div id="productTableWrap"> <table class="table table-striped" id="productTable"> <thead> <tr> <th>ID</th> <th>产品名称</th> <th>价格</th> <th>描述</th> </tr> </thead> <tbody id="productTableBody"> <tr><td colspan="4">请选择左侧分类查看产品</td></tr> </tbody> </table> </div>
然后在jsTree的切换事件中处理:
$('#jstree').on('changed.jstree', function (e, data) { const categoryId = data.selected[0]; const tableBody = $('#productTableBody'); // 未选中节点时重置提示 if (!categoryId) { tableBody.empty(); tableBody.append('<tr><td colspan="4">请选择左侧分类查看产品</td></tr>'); return; } // 发送AJAX请求 $.ajax({ url: '/YourController/Node', // 替换为你的控制器名称 type: 'GET', data: { categoryId: categoryId }, beforeSend: function () { // 显示加载状态 tableBody.empty(); tableBody.append('<tr><td colspan="4">加载中...</td></tr>'); }, success: function (products) { tableBody.empty(); // 遍历生成表格行 $.each(products, function (index, product) { const row = `<tr> <td>${product.Id}</td> <td>${product.ProductName}</td> <td>${product.Price}</td> <td>${product.Description}</td> </tr>`; tableBody.append(row); }); // 无产品时显示提示 if (products.length === 0) { tableBody.append('<tr><td colspan="4">当前分类暂无产品</td></tr>'); } }, error: function () { tableBody.empty(); tableBody.append('<tr><td colspan="4">加载产品数据失败,请重试</td></tr>'); } }); });
2. 对应部分视图返回的前端逻辑
右侧用一个空容器即可:
<div id="productTableWrap"> <p>请选择左侧分类查看产品</p> </div>
然后AJAX请求直接替换容器内容:
$('#jstree').on('changed.jstree', function (e, data) { const categoryId = data.selected[0]; const container = $('#productTableWrap'); if (!categoryId) { container.html('<p>请选择左侧分类查看产品</p>'); return; } $.ajax({ url: '/YourController/Node', type: 'GET', data: { categoryId: categoryId }, beforeSend: function () { container.html('<p>加载中...</p>'); }, success: function (html) { container.html(html); // 无产品时追加提示 if ($(html).find('tbody tr').length === 0) { container.append('<p class="mt-2">当前分类暂无产品</p>'); } }, error: function () { container.html('<p>加载产品数据失败,请重试</p>'); } }); });
三、额外注意事项
- 确保控制器路由正确:如果控制器使用了路由特性(比如
[Route("products")]),AJAX的url要对应调整(比如'/products/Node')。 - 处理分类层级:如果需要显示当前分类及所有子分类的产品,要修改EF Core查询逻辑,比如用递归查询获取所有子分类ID,再筛选产品。
- 防重复请求:可以在发送AJAX前取消之前的请求,避免多次切换节点导致的请求堆积。
内容的提问来源于stack exchange,提问作者Ben Weston
相关产品推荐
相关产品推荐

