一、HTML 文件详解
1. 基础结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>超市商品展示</title>
<style>...</style>
</head>
<body>
<h1>双叶超市商品列表</h1>
<table id="productTable">...</table>
<script src="script.js"></script>
</body>
</html>
<title>
:浏览器标签页标题。<style>
:内部CSS样式,定义页面外观。<body>
:页面可见内容。<h1>
:一级标题。<table>
:商品表格,id="productTable"
用于后续JavaScript操作。<script>
:引入外部的JavaScript文件script.js
。
2. 表格结构
<table id="productTable">
<thead>
<tr>
<th>商品 ID</th>
<th>商品名称</th>
<th>单价(元)</th>
<th>库存</th>
</tr>
</thead>
<tbody>
<!-- 动态内容区域 -->
</tbody>
</table>
<thead>
:表格的头部区域,通常包含标题行(<th>
)。<tbody>
:表格的主体区域,数据行(<tr>
和<td>
)将在这里动态插入。<tr>
:表格行(Table Row)。<th>
:表头单元格(Table Header),自动加粗居中。<td>
:普通单元格(Table Data)。
3. CSS 样式详解
body {
font-family: Arial, sans-serif; /* 使用Arial字体,无衬线字体更清晰 */
max-width: 800px; /* 页面最大宽度800像素 */
margin: 20px auto; /* 上下边距20px,左右自动(居中) */
padding: 20px; /* 内边距20px */
}
table {
width: 100%; /* 表格占满父容器宽度 */
border-collapse: collapse; /* 合并边框(相邻单元格边框合并为一条) */
box-shadow: 0 0 10px rgba(0,0,0,0.1); /* 添加阴影:X偏移0,Y偏移0,模糊10px,颜色黑色透明度0.1 */
}
th, td {
padding: 12px; /* 单元格内边距 */
text-align: left; /* 文字左对齐 */
border-bottom: 1px solid #e0e0e0; /* 底部边框:1px实线,浅灰色 */
}
th {
background-color: #f5f5f5; /* 表头背景色 */
font-weight: 600; /* 字体加粗(600相当于semibold) */
}
tr:hover {
background-color: #f9f9f9; /* 鼠标悬停时行背景色变为浅灰色 */
}
.no-data {
text-align: center; /* 无数据提示文字居中 */
padding: 20px; /* 内边距 */
}
二、JavaScript 文件详解
1. 整体执行流程
// 当页面内容加载完成后执行
document.addEventListener('DOMContentLoaded', async () => {
// 代码逻辑
});
DOMContentLoaded
事件:当HTML文档完全加载和解析完成(无需等待图片、样式表等)时触发,比window.onload
更快。async () => { ... }
:定义一个异步函数,用于处理需要等待的操作(如读取文件)。
2. 数据加载逻辑
try {
const response = await fetch('products.json'); // 1. 发起网络请求
if (!response.ok) throw new Error('文件读取失败'); // 2. 检查响应状态
const products = await response.json(); // 3. 解析JSON数据
renderProducts(products); // 4. 渲染数据
} catch (error) {
// 5. 错误处理
const tbody = document.querySelector('#productTable tbody');
tbody.innerHTML = `<tr class="no-data"><td colspan="4">${error.message}</td></tr>`;
}
fetch('products.json')
:向服务器请求products.json
文件,返回一个Promise。await
:等待Promise完成,获取响应对象response
。response.ok
:如果HTTP状态码在200-299范围内,返回true
,否则false
。response.json()
:将响应内容解析为JSON对象。catch
:捕获任何错误(如文件不存在、网络错误、JSON解析错误)。
3. 渲染函数 renderProducts
function renderProducts(products) {
const tbody = document.querySelector('#productTable tbody');
tbody.innerHTML = ''; // 清空表格
if (products.length === 0) {
tbody.innerHTML = '<tr class="no-data"><td colspan="4">当前没有商品数据</td></tr>';
return;
}
products.forEach(product => {
const row = document.createElement('tr'); // 创建行元素
row.innerHTML = `
<td>${product.id}</td>
<td>${product.name}</td>
<td>¥${product.price.toFixed(2)}</td>
<td>${product.stock}</td>
`;
tbody.appendChild(row); // 将行添加到表格
});
}
document.querySelector
:通过CSS选择器获取元素,#productTable tbody
表示选择id为productTable
的元素内部的tbody
。innerHTML = ''
:清空表格内容,避免重复渲染。product.price.toFixed(2)
:将价格保留两位小数(如5.5
→5.50
)。colspan="4"
:合并4列,用于显示无数据或错误提示。
三、关键概念解析
1. 为什么需要 DOMContentLoaded
?
如果JavaScript在HTML元素加载前执行,
document.querySelector
可能找不到元素,导致错误。DOMContentLoaded
确保代码在DOM树构建完成后执行,此时可以安全操作元素。
2. async/await
是什么?
异步编程:JavaScript默认是单线程的,遇到耗时操作(如网络请求)时会阻塞页面。异步编程允许代码在等待操作完成时继续执行其他任务。
async
:标记函数为异步函数,内部可以使用await
。await
:暂停异步函数的执行,等待Promise完成,然后继续执行。
3. fetch
API 的工作流程
发送请求 → 2. 等待响应 → 3. 检查状态 → 4. 解析数据 → 5. 处理错误。
4. 动态创建元素的两种方式
document.createElement
+appendChild
:const row = document.createElement('tr'); const cell = document.createElement('td'); cell.textContent = '数据'; row.appendChild(cell); tbody.appendChild(row);
innerHTML
:直接插入HTML字符串,更简洁但需要注意安全性(本例安全,因为数据来自本地文件)。
四、本地运行注意事项
1. 为什么需要 Live Server?
同源策略:浏览器禁止通过
file://
协议发起跨域请求(包括加载本地文件)。Live Server:通过
http://localhost
提供服务,绕过此限制。其他替代方案:VS Code插件、Python的http.server
模块等。
2. 如何创建 products.json
?
文件内容示例:
[ {"id": 1, "name": "苹果", "price": 5.5, "stock": 200}, {"id": 2, "name": "香蕉", "price": 3.2, "stock": 150} ]
注意事项:
字段名必须用双引号包裹。
数字无需引号,字符串需要引号。
文件必须与HTML文件在同一目录(或正确配置路径)。
五、调试技巧
1. 检查控制台错误
按 F12 打开开发者工具 → 查看 Console 标签页,任何JavaScript错误(如文件未找到、JSON解析错误)会在此显示。
2. 查看网络请求
在开发者工具中打开 Network 标签页 → 刷新页面 → 检查
products.json
请求是否成功,状态码是否为200。
3. 修改样式实时预览
在开发者工具的 Elements 标签页中,直接修改元素的CSS样式,实时查看效果。