在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
相关产品推荐
相关产品推荐

