
本文介绍如何将 php 查询的题库数据转为 json 供前端使用,并通过 javascript 实现按每题预设时间自动倒计时、无缝切换至下一条记录的轮播效果。
本文介绍如何将 php 查询的题库数据转为 json 供前端使用,并通过 javascript 实现按每题预设时间自动倒计时、无缝切换至下一条记录的轮播效果。
在构建在线测验、答题展示或教学轮播系统时,常需按固定时长逐条展示题目(如每题限时 15 秒),并在倒计时归零后自动跳转至下一题。直接在 PHP 中一次性渲染全部 <div class="area"> 元素虽可行,但会导致页面臃肿、DOM 冗余且难以动态控制切换逻辑;更优方案是<strong>服务端只提供结构化数据,由前端 JavaScript 主导状态管理与定时轮播</strong>。<h3>✅ 推荐实现思路</h3>
<ol>
<li>
<strong>PHP 端</strong>:使用 <code>fetch_all(MYSQLI_ASSOC) 获取全部题目记录,json_encode() 转为 JavaScript 可用的数组对象,并内联注入 <script></script>;
.area > .boxquestion 容器,内部用语义化 <i data-name="..."></i> 标签承载 ID、题目、倒计时内容;- 初始化显示第一条记录;
- 启动递归
setTimeout每秒执行一次; - 倒计时归零时自增索引
i,重置当前题目的time值; - 边界处理:超出数组长度时停止并显示“Finished”。
? 完整可运行示例(含样式与脚本)
<meta charset="UTF-8"><title>题目轮播系统</title><style>
.area { height: 100vh; width: 100%; overflow: hidden; }
.boxquestion { padding: 2rem; text-align: center; }
[data-name] {
display: block;
margin: 0.8rem auto;
padding: 0.75rem 1.5rem;
border-radius: 4px;
font-weight: bold;
min-width: 12rem;
}
[data-name='number'] { background: #28a745; color: white; }
[data-name='question'] { background: #ffc107; color: #007bff; }
[data-name='countdown'] { background: #dc3545; color: white; font-size: 1.4rem; }
</style><?php $mysqli = new mysqli("localhost", "root", "", "learningbydoing");
if ($mysqli->connect_error) die("数据库连接失败: " . $mysqli->connect_error);
$result = $mysqli->query("SELECT `no` AS id, `question`, `time` FROM question");
$records = $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
echo "<script>const QUESTIONS = " . json_encode($records) . ";</script>";
?>
<div class="area">
<div class="boxquestion">
<i data-name="number"></i>
<i data-name="question"></i>
<i data-name="countdown"></i>
</div>
</div>
<script>
const numberEl = document.querySelector('i[data-name="number"]');
const questionEl = document.querySelector('i[data-name="question"]');
const countdownEl = document.querySelector('i[data-name="countdown"]');
// 边界保护:无数据时不执行
if (!QUESTIONS || QUESTIONS.length === 0) {
numberEl.textContent = '—';
questionEl.textContent = '暂无题目';
countdownEl.textContent = '—';
console.warn('题目数据为空');
return;
}
let currentIndex = 0;
let remainingTime = QUESTIONS[0].time;
// 初始化首题
numberEl.textContent = QUESTIONS[0].id;
questionEl.textContent = QUESTIONS[0].question;
countdownEl.textContent = remainingTime;
// 递归倒计时主循环
function startCountdown() {
remainingTime--;
// 更新倒计时显示(+1 是因先减再显示,保证从原始值开始)
countdownEl.textContent = remainingTime + 1;
if (remainingTime <= 0) {
currentIndex++;
if (currentIndex >= QUESTIONS.length) {
// 全部展示完毕
clearInterval(timerId);
numberEl.textContent = '✓';
questionEl.textContent = '全部完成!';
countdownEl.textContent = '—';
return;
}
// 加载下一题
const next = QUESTIONS[currentIndex];
numberEl.textContent = next.id;
questionEl.textContent = next.question;
remainingTime = next.time;
}
}
const timerId = setInterval(startCountdown, 1000);
</script>
⚠️ 注意事项与优化建议
-
安全性:生产环境务必对
$mysqli->query()参数做预处理(PDO 预处理语句或mysqli_real_escape_string),防止 SQL 注入; -
健壮性:添加
try/catch包裹数据库操作,QUESTIONS空数组判断避免 JS 报错; - 用户体验:可扩展支持「暂停/手动翻页」「进度条可视化」「声音提示」等功能;
- 性能:若题目量极大(>1000 条),建议改用分页 + 懒加载,避免 JSON 过大阻塞首屏渲染;
-
兼容性:上述代码兼容现代浏览器(Chrome/Firefox/Edge/Safari),如需支持 IE,请替换
const为var并避免箭头函数。
该方案解耦了前后端职责——PHP 专注数据交付,JavaScript 专注交互逻辑,结构清晰、易于维护,是实现动态倒计时轮播的理想实践。











