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

在Django模板中用JS实现测验两阶段无刷新切换及标签操作

Django测验应用两阶段无刷新交互实现

我开发的Django测验应用分为两个阶段:

  • 第一阶段:分页展示10条带音频的句子(每页1条),浏览完所有句子后显示「continue」按钮
  • 第二阶段:不刷新页面(复用已加载的对象列表,避免重复查询数据库),切换内容显示逻辑(比如仅展示音频隐藏文本,或仅展示文本隐藏音频),添加输入框供用户作答,再次循环同一组对象出题

原代码已实现第一阶段分页,但阶段切换逻辑杂乱,以下是优化后的JS解决方案:

优化后的模板代码

<button id="prev">prev</button>
<button id="next">next</button>
<button id="continue-btn" style="display: none;">Continue to Quiz</button>
<ul class="list-articles" id="content-container"></ul>
<!-- 第二阶段输入区域,默认隐藏 -->
<div id="quiz-input-area" style="display: none;">
  <textarea id="user-answer" placeholder="Enter your answer here..."></textarea>
</div>

<script>
// 从视图获取的对象列表(移除原代码多余的冒号)
var my_objects = {{ my_objects|safe }};
// 状态管理变量
let currentStage = 'browse'; // 'browse' 浏览阶段 / 'quiz' 测验阶段
let page_number = 0;
const totalItems = my_objects.length;

// 渲染当前页面内容的通用函数
function renderCurrentPage() {
  const container = document.getElementById('content-container');
  const quizInputArea = document.getElementById('quiz-input-area');
  const continueBtn = document.getElementById('continue-btn');
  const currentItem = my_objects[page_number].fields;

  container.innerHTML = '';

  if (currentStage === 'browse') {
    // 浏览阶段:显示完整文本+音频
    container.innerHTML = `
      <li>
        <h1>${currentItem.content}</h1>
      </li>
    `;
    const audio = document.createElement('audio');
    audio.src = `/media/${currentItem.audio}`;
    container.appendChild(audio);

    // 最后一页显示continue按钮
    continueBtn.style.display = page_number === totalItems - 1 ? 'block' : 'none';
    // 显示分页按钮,隐藏输入区域
    document.getElementById('prev').style.display = 'inline-block';
    document.getElementById('next').style.display = 'inline-block';
    quizInputArea.style.display = 'none';
  } else if (currentStage === 'quiz') {
    // 测验阶段:仅显示音频(可根据需求修改为仅显示文本)
    const audio = document.createElement('audio');
    audio.src = `/media/${currentItem.audio}`;
    container.appendChild(audio);
    // 显示输入区域,隐藏continue按钮
    quizInputArea.style.display = 'block';
    continueBtn.style.display = 'none';
    // 分页按钮始终显示
    document.getElementById('prev').style.display = 'inline-block';
    document.getElementById('next').style.display = 'inline-block';
  }

  // 更新隐藏页码(如需提交表单使用)
  const pageInput = document.getElementById('page_number');
  if (pageInput) pageInput.value = page_number;
}

// 分页逻辑函数
function paginate(action) {
  if (currentStage === 'browse') {
    // 浏览阶段:限制页码边界,不循环
    if (action === 'next' && page_number < totalItems - 1) {
      page_number++;
    } else if (action === 'prev' && page_number > 0) {
      page_number--;
    }
  } else if (currentStage === 'quiz') {
    // 测验阶段:循环遍历,到边界后跳转
    if (action === 'next') {
      page_number = (page_number + 1) % totalItems;
    } else if (action === 'prev') {
      page_number = page_number === 0 ? totalItems - 1 : page_number - 1;
    }
  }
  renderCurrentPage();
}

// 页面初始化
document.addEventListener('DOMContentLoaded', function() {
  // 渲染初始页面
  renderCurrentPage();

  // 绑定分页按钮事件
  document.getElementById('next').onclick = () => paginate('next');
  document.getElementById('prev').onclick = () => paginate('prev');

  // 绑定continue按钮事件,切换到测验阶段
  document.getElementById('continue-btn').onclick = function() {
    currentStage = 'quiz';
    page_number = 0; // 从第一条开始测验
    renderCurrentPage();
  };
});
</script>

关键优化说明

  • 状态集中管理:用currentStage和page_number统一控制当前阶段与页码,避免零散的DOM判断逻辑
  • 通用渲染函数:renderCurrentPage根据阶段渲染对应内容,减少重复代码,逻辑更易维护
  • 边界与循环处理:浏览阶段限制页码范围,测验阶段实现循环遍历,符合不同阶段的交互需求
  • DOM显隐统一控制:通过style.display管理按钮、输入区域的显示/隐藏,替代杂乱的标签禁用/激活操作
  • 复用对象列表:全程使用已加载的my_objects,无需重新查询数据库,提升性能

内容的提问来源于stack exchange,提问作者O'nayd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:35:16