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

如何用jQuery遍历多份JSON文件构建在线测验页面

解决异步AJAX顺序问题及数据关联渲染的方案

看起来你遇到的核心问题有两个:异步请求的执行顺序不可控,导致DOM渲染时机不对;数据没有通过关联ID正确匹配,导致内容乱套。别担心,我们一步步来解决:

问题根源拆解

  1. 三个$.ajax是并行发起的,谁先返回谁先执行回调,可能出现答案先渲染但题目DOM还没生成,或者题目先渲染但分类容器还没创建的情况。
  2. 当前代码中,添加问题时会把同一个题目插入到所有.section-bottom容器中,添加答案时也会把同一个选项插入到所有answerContainer里,完全没有按分类-题目-选项的层级匹配。

完整解决方案

我们先一次性获取所有三个数据源,等全部拿到后再按分类→题目→选项的顺序关联数据并渲染DOM,既保证顺序,又能精准匹配内容。

HTML部分(保持不变)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>quiz</title>
</head>
<body>
<div id="bigMain" class="hide">
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="js/refactor3.js"></script>
</body>
</html>

JavaScript修改版

// 先发起三个请求,暂不处理回调
var request1 = $.ajax({
    url: 'https://api.myjson.com/bins/nilct',
    dataType: 'json',
    type: 'get',
    cache: false
});

var request2 = $.ajax({
    url: 'https://api.myjson.com/bins/1178p1',
    dataType: 'json',
    type: 'get',
    cache: false
});

var request3 = $.ajax({
    url: 'https://api.myjson.com/bins/qhft1',
    dataType: 'json',
    type: 'get',
    cache: false
});

// 等待三个请求全部完成后再统一处理
$.when(request1, request2, request3).done(function(categoriesRes, questionsRes, answersRes) {
    // 提取每个请求的返回数据
    const categories = categoriesRes[0];
    const questions = questionsRes[0];
    const answers = answersRes[0];
    
    const bigMain = $('#bigMain');
    bigMain.removeClass('hide'); // 显示主容器

    // 遍历每个分类,逐层渲染
    categories.forEach(category => {
        const categoryId = category.id;
        // 创建分类section容器
        const section = $(`
            <section id="${categoryId}">
                <div class="section-top">
                    <p class="title optionsTitle ${category.category} titleFor_${categoryId}">
                        ${category.category}
                    </p>
                    <hr class="hideOnMobile">
                    <h1 class="top-title">${category.header}</h1>
                </div>
                <div class="section-bottom"></div>
            </section>
        `);
        bigMain.append(section);
        
        // 筛选当前分类下的所有题目
        const categoryQuestions = questions.filter(q => q.category_id === categoryId);
        const sectionBottom = section.find('.section-bottom');
        
        // 遍历当前分类的题目
        categoryQuestions.forEach(question => {
            const questionId = question.id;
            // 创建题目元素
            const questionElement = $(`
                <div class="question question${categoryId}">
                    <p class="questionP questionId_${questionId}">${question.question}</p>
                    <ul id="questionId-${questionId}" class="answerContainer"></ul>
                </div>
            `);
            sectionBottom.append(questionElement);
            
            // 筛选当前题目对应的选项(按orderNum匹配,可根据实际JSON结构调整)
            const questionAnswers = answers.filter(a => a.orderNum === question.orderNum);
            const answerContainer = questionElement.find('.answerContainer');
            
            // 遍历并添加选项
            questionAnswers.forEach(answer => {
                const answerElement = $(`
                    <li>
                        <input type="radio" name="question-${questionId}" value="${answer.answer}">
                        ${answer.answer}
                    </li>
                `);
                answerContainer.append(answerElement);
            });
        });
    });
}).fail(function(err) {
    console.error('请求失败:', err);
});

关键改进说明

  1. 用$.when控制异步顺序:确保所有数据都获取完成后再开始渲染,彻底避免异步回调顺序混乱的问题。
  2. 层级化数据匹配:
    • 每个分类下筛选category_id匹配的题目
    • 每个题目下筛选关联字段匹配的选项(这里用orderNum,如果你的JSON里有question_id字段,用它匹配会更准确)
  3. 精准DOM插入:创建分类后直接在当前分类的底部插入题目,创建题目后直接在当前题目选项容器插入选项,完全避免了之前“一对多”插入的错误。
  4. 修复单选按钮逻辑:把radio的name属性改为题目ID(name="question-${questionId}"),保证同一题的选项互斥,之前的answerOrderNum会导致不同题的选项互斥,这是个隐性bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:10:15