棒!按你的截图,我们把“HTTP 状态码演示”拆成一个最小可运行组件(三个文件)。功能:选择状态码 → 点击“发起请求” → 发送 fetch 请求到 https://httpstat.us/<code>,便于学生在 Network 面板观察请求/响应头、状态码、Cookie 等;同时在页面提示本次结果。该练习与课程标准中“理解HTTP请求/响应结构及常见状态码;能用DevTools抓包与识别状态码”的能力点一致。
http-status.html(逐行注释)<!DOCTYPE html> <!-- 启用 HTML5 标准模式 -->
<html lang="zh-CN"> <!-- 页面主语言为中文 -->
<head> <!-- 文档头部 -->
<meta charset="UTF-8"> <!-- UTF-8 防止中文乱码 -->
<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 移动端友好 -->
<title>HTTP 状态码演示</title> <!-- 标签栏标题 -->
<link rel="stylesheet" href="style.css"> <!-- 引入公共样式(按钮/卡片等) -->
<style>
/* 组件局部样式(可放到 style.css 中) */
.card{max-width:1100px;margin:24px auto;padding:20px;border:1px solid #dee2e6;border-radius:12px}
.row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
select{height:40px;padding:0 10px;border:1px solid #ced4da;border-radius:6px;font-size:16px}
.btn{display:inline-flex;align-items:center;justify-content:center;height:40px;padding:0 16px;border-radius:6px;border:1px solid #0d6efd;background:#0d6efd;color:#fff;cursor:pointer}
.btn:disabled{opacity:.6;cursor:not-allowed}
.tip{margin-top:12px;color:#6c757d}
.result{margin-top:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.ok{color:#0a7d2d} .err{color:#c1121f}
</style> <!-- 简单内联样式,方便拷贝即用 -->
</head>
<body> <!-- 页面主体开始 -->
<section class="card"> <!-- 外层卡片容器 -->
<h2>HTTP 状态码演示</h2> <!-- 模块标题,与截图一致 -->
<div class="row"> <!-- 横向排布:选择框 + 按钮 -->
<label for="code">选择状态码:</label> <!-- 选择框说明 -->
<select id="code"> <!-- 下拉选择不同状态码 -->
<option value="200" selected>200</option> <!-- 成功 -->
<option value="301">301</option> <!-- 永久重定向 -->
<option value="302">302</option> <!-- 临时重定向 -->
<option value="400">400</option> <!-- 客户端错误 -->
<option value="401">401</option> <!-- 未授权 -->
<option value="403">403</option> <!-- 禁止访问 -->
<option value="404">404</option> <!-- 未找到 -->
<option value="500">500</option> <!-- 服务器错误 -->
</select>
<button id="send" class="btn">发起请求</button> <!-- 触发请求按钮 -->
</div>
<p class="tip">在 Network 面板查看请求与响应头、Cookie 等。</p> <!-- 教学提示语 -->
<div id="result" class="result"></div> <!-- 用于显示本次请求结果 -->
</section>
<script src="http-status.js"></script> <!-- 交互脚本 -->
</body>
</html>
style.css(可与前面组件共用)/* 基础:让外观干净、易读 */
*{box-sizing:border-box} /* 盒模型含内边距/边框 */
body{margin:0;padding:24px;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans SC",Arial,sans-serif;color:#212529;background:#fff;line-height:1.6}
a{text-decoration:none}
若你已经有站点的全局样式,这个 style.css 可省略或合并。
http-status.js(逐行注释)// 1) 选择相关 DOM 元素
const select = document.getElementById('code'); // 下拉选择状态码
const sendBtn = document.getElementById('send'); // “发起请求”按钮
const resultBox = document.getElementById('result'); // 展示结果的区域
// 2) 点击按钮时触发请求
sendBtn.addEventListener('click', async () => { // 绑定点击事件(异步函数便于使用 await)
const code = select.value; // 读取当前选中的状态码
const url = `https://httpstat.us/${code}`; // 演示服务:按路径返回对应状态码(支持 CORS)
// 2.1 UI:禁用按钮,避免重复点击
sendBtn.disabled = true; // 禁用按钮
sendBtn.textContent = '请求中…'; // 反馈给用户
try {
// 2.2 发起请求;redirect: "manual" 可在 30x 时保留重定向响应,便于观察
const res = await fetch(url, { redirect: 'manual' }); // 发起 GET 请求
// 2.3 读取部分信息(注意:跨域时某些头可能不可见,足以展示状态码)
const status = res.status; // HTTP 状态码(200/302/404/…)
const redirected = res.type === 'opaqueredirect' || res.redirected; // 是否发生重定向(不同实现差异)
const contentType = res.headers.get('content-type'); // 可能的响应类型
// 2.4 将观察到的结果输出到页面,便于和 Network 面板对照
resultBox.innerHTML =
`<div>请求地址:<code>${url}</code></div>
<div>状态码:<strong class="${status>=200&&status<400?'ok':'err'}">${status}</strong></div>
<div>是否重定向:${redirected ? '是' : '否'}</div>
<div>Content-Type:${contentType || '(不可见或无)'}</div>`;
// 2.5 教学点:控制台也输出,方便老师示范
console.log('[HTTP DEMO]', { url, status, redirected, contentType });
} catch (err) {
// 2.6 异常处理(如断网/被拦截):在页面给出友好提示
resultBox.innerHTML = `<div class="err">请求失败:${err.message}</div>`;
} finally {
// 2.7 还原按钮状态
sendBtn.disabled = false;
sendBtn.textContent = '发起请求';
}
});
// 3) 便于课堂演示:回车键也能发起请求(可选)
select.addEventListener('keydown', e => {
if (e.key === 'Enter') sendBtn.click(); // 按下回车触发按钮点击
});
200 → 302 → 404 → 500,让学生在 Network 面板中观察:
200:改用本地 ok.json 文件并 fetch('./ok.json');404:请求一个不存在的本地路径 fetch('./not-exist.json');302:新建 redirect.html,在其中用
setTimeout(()=>location.replace('final.html'),500) 或 <meta http-equiv="refresh" content="0;url=final.html"> 模拟。如果你愿意,我可以把这个组件再打包成一页可直接嵌入你博客的 demo.html 区块,或者按你现有样式系统(按钮、卡片)做成完全一致的 UI。