You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:57:01