JS使用XMLHttpRequest拉取MySQL数据填充select卡顿如何优化?
问题核心原因
你的代码最大的性能问题出在循环里直接操作innerHTML拼接,每次执行jsSelBenEmpNo.innerHTML +=都会触发浏览器对整个select元素的DOM重解析、重排、重绘,4000次循环就会触发4000次DOM操作,这是耗时50秒的核心原因。
而PHP直出的方案是一次性把所有HTML渲染完成再交给浏览器解析,只触发一次DOM更新,所以速度快。
优化方案
1. 核心优化:拼接HTML字符串后一次性赋值
把所有option的HTML先拼到一个临时字符串里,循环结束后一次性赋值给select的innerHTML,只触发一次DOM更新,改完后4000条数据渲染基本可以控制在100ms以内,不会有卡顿。
优化后的JS代码:
function jsonload() { let jsSelBenEmpNo = document.getElementById("BenEmpNo"); let jsBenEmpNoDataAry; // 先初始化基础option,统一放到临时字符串里拼接 let htmlStr = "<option value='-select-'>-Select-</option>"; oReq = new XMLHttpRequest(); oReq.open('POST', "../php/oh-get_BenEmpNo.php", true); oReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); oReq.onload = function () { jsBenEmpNoAry = this.responseText.split('|'); for (let i = 1; i < jsBenEmpNoAry.length; i++) { jsBenEmpNoDataAry = jsBenEmpNoAry[i].split('~'); // 只做字符串拼接,不操作DOM htmlStr += "<option value='" + jsBenEmpNoDataAry[0] +"'>" + "(" + jsBenEmpNoDataAry[0] + ")" + jsBenEmpNoDataAry[1] + "</option>"; } // 一次性赋值,仅触发1次DOM更新 jsSelBenEmpNo.innerHTML = htmlStr; } oReq.send("parsparm=" + "|"); }
2. 可选优化:后端改用JSON格式返回数据
你现在用|和~手动拆分字符串的方式容易出错,也可以改成后端直接返回JSON数组,前端直接解析即可,代码可维护性更高:
优化后的PHP代码:
<?php $sql = "select EmpNo, EngName from beneficiary"; require_once("oh-dbcon.php"); $data = []; if ($result = mysqli_query($db_con, $sql)) { while ($row = mysqli_fetch_assoc($result)) { $data[] = $row; }; echo json_encode(['code'=>0, 'data'=>$data]); }else echo json_encode(['code'=>1, 'msg'=>"ERROR Result (". mysqli_error($db_con) . ")-(". $sql .")"]); mysqli_close($db_con); ?>
对应的JS解析部分:
oReq.onload = function () { const res = JSON.parse(this.responseText); if(res.code === 0) { res.data.forEach(item => { htmlStr += `<option value="${item.EmpNo}">(${item.EmpNo})${item.EngName}</option>`; }) jsSelBenEmpNo.innerHTML = htmlStr; } else { console.error(res.msg); } }
3. 进阶体验优化
- 如果后续数据量继续增大到万级以上,可以用虚拟滚动方案只渲染可视区域内的option,进一步降低DOM节点数量,提升交互体验。
- 可以给select搭配搜索筛选功能,用户输入关键词后只渲染匹配的option,不用每次翻找4000条选项,使用效率更高。
内容的提问来源于stack exchange,提问作者gamal.sallam
相关产品推荐
相关产品推荐

