JqGrid更新后数据不刷新?详解原因及解决方案
2025-03-18 23:00:31
JqGrid 更新后数据不刷新的问题及解决方案
接手了一个 PHP 发票应用,发现发票详情页的 JqGrid 在更新数据后,表格内容不会自动刷新,必须手动刷新整个页面才能看到更新后的数据。 增加和删除功能倒是没问题,就是这个编辑功能有点小毛病。 捣鼓了半天, JavaScript 和 JQuery 水平有限,一直没搞定。下面细说一下这个问题和解决办法。
一、 问题原因分析
根据代码和现象来看,问题出在 edit
操作上。 虽然数据库更新成功了,但 JqGrid 没有重新加载数据。 核心原因在于,虽然在successfunc
里有尝试刷新页面: window.location.reload(false);
, 但这相当于重新加载了整个网页,而不是单单刷新 JqGrid 的数据。 在 inline editing 的情景下,期望的是无刷新更新 JqGrid 数据。 并且发现,代码中 reloadAfterSubmit
和 afterSubmit
并未完全发挥作用。
二、 解决方案
既然知道问题是 JqGrid 没有正确地重新加载数据, 解决方法就是强制让它在编辑操作成功后重新加载数据。 有几个办法可以做到。
1. 使用 trigger("reloadGrid")
(推荐)
这是最直接有效的方法。在数据更新成功的回调函数中,直接触发 JqGrid 的 reloadGrid
事件,强制 JqGrid 重新向服务器请求数据。
-
原理:
trigger("reloadGrid")
会告诉 jqGrid 重新加载数据。 如果datatype
设置为 'json',jqGrid 会再次发送请求到url
指定的地址,获取最新的数据并渲染表格。 -
代码示例:
修改
editOptions
对象:var editOptions = { keys: true, mtype: "POST", successfunc: function (response) { //原来使用了不太恰当的方式去尝试更新grid, 先注释掉: // var $self = $(list); // setTimeout(function () { // window.location.reload(false); // }, 50); //判断如果PHP成功执行返回的是true if (response.responseText == 'true') { //触发刷新动作 $("#list").trigger("reloadGrid"); return true; } return false; //返回false给jqGrid说明有问题,它会保持编辑状态 } };
在 PHP 代码的
edit
部分,确保editdetails
执行成功后,$success
的值为 "true" 的字符串://changes don't refresh grid elseif($oper == "edit") { $Quantity = $_POST['Quantity']; $ProductID = $_POST['ProductID']; $UnitPrice = $_POST['UnitPrice']; $ExtendedPrice = $UnitPrice*$Quantity; $qeditdetails = "UPDATE tblorderdetails SET quantity = ?, price = ?, extended_price = ? WHERE product_id = ? AND order_id = ?"; $editdetails = $pdo->prepare($qeditdetails); $editdetails->execute([$Quantity,$UnitPrice,$ExtendedPrice,$ProductID,$OrderID]); if ($editdetails) { $success = "true"; } //保持这个是string else{ $success = "false"; } //明确的加上如果数据库操作不成功的返回, 协助调试(这行可以按需选择加不加). }
-
说明: 这里添加了对服务器返回值的判断 (
response.responseText == 'true'
),确保只有在服务器端处理成功后才刷新表格。 避免了由于服务器端错误或其他原因导致的不必要刷新。 同时让jqGrid理解服务器的操作是否成功。
2. 使用 setGridParam
和 trigger("reloadGrid")
结合 (适用于更复杂场景)
这种方法允许在重新加载数据之前,动态修改 JqGrid 的参数,例如改变请求的 URL、参数等。
-
原理: 先通过
setGridParam
修改 JqGrid 的配置参数(比如url
、postData
),然后再调用trigger("reloadGrid")
触发数据重新加载。 -
代码示例:
var editOptions = { keys: true, mtype: "POST", successfunc: function () { // 修改参数(如果需要),这里假设要加一个参数 newParam $("#list").jqGrid('setGridParam', { url: 'orderdetails_json.php', // 或者新的 URL, 根据你的场景来 datatype: 'json', // 明确类型. postData: {newParam: 'newValue'}, page: 1 // 重置到第一页,按需选择加不加 }).trigger("reloadGrid"); return [true]; //返回给jqGrid让它完成后续流程 } };
-
说明: 此处假设更改
url
和postData
, 需要根据自己的需求, 选择适合的修改即可。 也可以仅仅修改datatype
后 reload.
3. (备选, 但更不推荐)移除 loadonce:false
, 调整成loadonce:true
(只适用于数据量小的情况)
如果数据量不大,可以考虑将loadonce
设置为 true
。 第一次加载后,后续的操作都是在本地(浏览器)进行。
-
原理 : 第一次从服务器获取所有数据,之后所有排序、分页、筛选操作都在客户端完成,不再向服务器发送请求。 更新完数据, 仅需重新渲染。
-
代码示例:
// 在 jqGrid 初始化部分,把loadonce设置为true $grid.jqGrid({ //其他属性.... loadonce:true, //....其他属性 })
修改 successfunc 部分的代码:
successfunc: function (response) { if(response.responseText == "true"){ // 如果是 loadonce: true 模式, 可以在成功后手动刷新表格的 data var grid = $("#list")[0]; // 获取 grid 对象 grid.addJSONData(response.newData); //这里需要服务器配合返回新的rowData, 这比较麻烦. // 或者尝试 $("#list").trigger("reloadGrid"); 也可以尝试是否有效(但不一定) return true; } }
-
说明: 此方法需要调整服务器端的返回格式,需要
response
里带上修改后的行数据(newData
)。 操作较繁琐。且仅适用于数据集小,且不需要频繁与服务器交互的场景。 -
重要提示 : 大部分场景不建议用此方案, 前两种更推荐.
安全建议
- 输入验证: PHP 代码中,虽然使用了预处理语句(Prepared Statements),有效防止了 SQL 注入,但在处理用户输入时,仍然建议进行数据类型和格式的验证,例如验证
Quantity
、UnitPrice
是否为数字。 - 错误处理: 建议在 PHP 代码中增加更详细的错误处理,例如使用
try...catch
块捕获 PDO 异常,记录详细错误信息,并向前端返回更友好的错误提示。 - XSS 防护 : 确保用户输入的
Description
内容经过了适当的过滤或转义,防止跨站脚本攻击(XSS)。 JqGrid 本身输出数据时候会进行处理, 但良好的习惯是永远做好输入输出的处理。
进阶使用:
-
自定义错误处理: JqGrid 的
errorfunc
选项可以用来处理编辑过程中的错误。可以在errorfunc
中显示自定义的错误消息,或者进行其他的错误处理操作。 -
本地数据编辑 (Client-side Editing): 对于小数据量的表格, 设置
datatype: "local"
,完全在客户端进行数据操作. 更复杂的使用也可以结合data
选项来实现预先加载一部分,后续更新部分数据的更复杂的操作. -
优化数据加载 : 数据量大的表格,优化数据加载可以显著的提高性能, 利用jqGrid提供的
gridview:true
来提速.gridview:true
的作用是让jqGrid先构建好整个HTML再添加到页面DOM树里。而不是逐行添加DOM节点。这样一次性的添加到DOM中要快。
希望上面几个解决办法能帮你解决表格数据更新问题! 记住,trigger("reloadGrid")
通常是解决这类问题的最直接、最有效的手段。 根据实际情况,你还可以结合使用 setGridParam
来灵活地控制表格的重新加载行为.