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

如何解构JSON文件并在站点展示内容?加载大量对象致Chrome崩溃

解决大量JSON数据加载导致浏览器崩溃的问题

问题根源

你当前的代码在循环里每次都执行con.innerHTML += ...,这会频繁触发浏览器的DOM重排与重绘,当数据量达到数千条时,主线程被持续阻塞,最终导致浏览器崩溃。


解决方案1:批量插入DOM,减少重绘次数

把所有元素先组装到文档片段或者字符串中,一次性插入DOM,避免频繁修改页面结构。

方案1.1 使用DocumentFragment(推荐,性能更优)

function info(x){
    const fragment = document.createDocumentFragment();
    x.messages.forEach(element => {
        const p = document.createElement('p');
        p.textContent = `${element.creator.name}: ${element.text}`;
        fragment.appendChild(p);
    });
    con.appendChild(fragment);
}

方案1.2 拼接HTML字符串后一次性赋值

function info(x){
    let htmlStr = '';
    x.messages.forEach(element => {
        htmlStr += `<p>${element.creator.name}: ${element.text}</p>`;
    });
    con.innerHTML = htmlStr; // 一次性替换,而非累加
}

解决方案2:分批渲染+空闲执行

把数据拆分成小批次,利用浏览器空闲时间逐步渲染,避免主线程长时间被占用。

async function getData(){
    const response = await fetch(url);
    const data = await response.json();
    const batchSize = 50; // 每批渲染50条,可根据性能调整
    let currentIndex = 0;

    function renderNextBatch(){
        const endIndex = Math.min(currentIndex + batchSize, data.messages.length);
        const fragment = document.createDocumentFragment();
        
        for(let i = currentIndex; i < endIndex; i++){
            const element = data.messages[i];
            const p = document.createElement('p');
            p.textContent = `${element.creator.name}: ${element.text}`;
            fragment.appendChild(p);
        }
        
        con.appendChild(fragment);
        currentIndex = endIndex;

        // 还有未渲染的数据,就放到浏览器空闲时继续
        if(currentIndex < data.messages.length){
            requestIdleCallback(renderNextBatch);
            // 兼容性不好的话可以用 setTimeout(renderNextBatch, 0)
        }
    }

    renderNextBatch();
}

解决方案3:虚拟滚动(处理超大量数据最优)

只渲染当前视口内的内容,当用户滚动时动态加载/替换可见区域的数据,彻底避免一次性渲染数千条DOM的问题。核心思路是监听滚动事件,计算可见区域范围,只渲染对应范围内的数据。

简化版示例:

async function getData(){
    const response = await fetch(url);
    const data = await response.json();
    const messages = data.messages;
    const container = con;
    const itemHeight = 20; // 假设每条消息高度固定为20px
    container.style.height = `${messages.length * itemHeight}px`; // 设置容器总高度

    // 监听滚动事件,渲染可见区域的消息
    container.addEventListener('scroll', () => {
        const scrollTop = container.scrollTop;
        const visibleStart = Math.floor(scrollTop / itemHeight);
        const visibleEnd = Math.min(visibleStart + 50, messages.length); // 渲染当前视口+额外50条避免空白
        
        // 清空当前可见区域外的内容,只保留可见部分
        container.innerHTML = '';
        const fragment = document.createDocumentFragment();
        
        for(let i = visibleStart; i < visibleEnd; i++){
            const element = messages[i];
            const p = document.createElement('p');
            p.textContent = `${element.creator.name}: ${element.text}`;
            p.style.position = 'absolute';
            p.style.top = `${i * itemHeight}px`;
            fragment.appendChild(p);
        }
        
        container.appendChild(fragment);
    });

    // 初始渲染第一屏
    container.dispatchEvent(new Event('scroll'));
}

额外注意事项

  • 优先使用textContent而非HTML字符串拼接,避免潜在的XSS风险(如果JSON数据包含用户输入内容)。
  • 避免在循环中直接操作DOM,任何DOM操作都应该尽量批量执行。

内容的提问来源于stack exchange,提问作者Preetham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:45:08