实战演练:通过API获取商品详情并展示
下面我将演示如何通过API获取商品详情并在网页中展示。我们将使用JavaScript的Fetch API来获取数据,并使用HTML/CSS来展示结果。
1. 准备工作
假设我们有一个提供商品详情的API端点,例如:
https://api.example.com/products/{productId}
2. HTML结构
html
<!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> |
body { |
font-family: 'Arial', sans-serif; |
line-height: 1.6; |
max-width: 800px; |
margin: 0 auto; |
padding: 20px; |
color: #333; |
} |
.product-container { |
display: flex; |
flex-wrap: wrap; |
gap: 20px; |
margin-top: 20px; |
} |
.product-image { |
flex: 1; |
min-width: 300px; |
} |
.product-image img { |
max-width: 100%; |
height: auto; |
border-radius: 8px; |
} |
.product-details { |
flex: 1; |
min-width: 300px; |
} |
.product-title { |
font-size: 24px; |
margin-bottom: 10px; |
color: #2c3e50; |
} |
.product-price { |
font-size: 28px; |
color: #e74c3c; |
margin: 15px 0; |
} |
.product-description { |
margin: 20px 0; |
color: #7f8c8d; |
} |
.loading { |
text-align: center; |
padding: 20px; |
font-size: 18px; |
} |
.error { |
color: #e74c3c; |
text-align: center; |
padding: 20px; |
} |
button { |
background-color: #3498db; |
color: white; |
border: none; |
padding: 10px 20px; |
border-radius: 4px; |
cursor: pointer; |
font-size: 16px; |
margin-top: 10px; |
} |
button:hover { |
background-color: #2980b9; |
} |
</style> |
</head> |
<body> |
<h1>商品详情</h1> |
<div> |
<label for="productId">输入商品ID:</label> |
<input type="text" id="productId" placeholder="例如: 123"> |
<button id="fetchBtn">获取商品详情</button> |
</div> |
<div id="productContainer" class="product-container" style="display: none;"> |
<div class="product-image"> |
<img id="productImage" src="" alt="商品图片"> |
</div> |
<div class="product-details"> |
<h2 id="productTitle" class="product-title"></h2> |
<div id="productPrice" class="product-price"></div> |
<div id="productRating"></div> |
<div id="productStock"></div> |
<div id="productDescription" class="product-description"></div> |
<button id="addToCartBtn">加入购物车</button> |
</div> |
</div> |
<div id="loading" class="loading" style="display: none;">加载中...</div> |
<div id="error" class="error" style="display: none;"></div> |
<script src="app.js"></script> |
</body> |
</html> |
3. JavaScript代码 (app.js)
javascript
document.addEventListener('DOMContentLoaded', function() { |
const fetchBtn = document.getElementById('fetchBtn'); |
const productIdInput = document.getElementById('productId'); |
const productContainer = document.getElementById('productContainer'); |
const loadingElement = document.getElementById('loading'); |
const errorElement = document.getElementById('error'); |
// 模拟API端点 - 实际使用时替换为真实的API URL |
const API_BASE_URL = 'https://api.example.com/products'; |
fetchBtn.addEventListener('click', fetchProductDetails); |
function fetchProductDetails() { |
const productId = productIdInput.value.trim(); |
if (!productId) { |
showError('请输入有效的商品ID'); |
return; |
} |
// 显示加载状态 |
loadingElement.style.display = 'block'; |
productContainer.style.display = 'none'; |
errorElement.style.display = 'none'; |
// 构建API URL |
const apiUrl = `${API_BASE_URL}/${productId}`; |
// 使用Fetch API获取数据 |
fetch(apiUrl) |
.then(response => { |
if (!response.ok) { |
throw new Error(`HTTP error! status: ${response.status}`); |
} |
return response.json(); |
}) |
.then(data => { |
// 成功获取数据后隐藏加载状态 |
loadingElement.style.display = 'none'; |
// 展示商品详情 |
displayProductDetails(data); |
}) |
.catch(error => { |
console.error('获取商品详情失败:', error); |
loadingElement.style.display = 'none'; |
showError(`获取商品详情失败: ${error.message}`); |
}); |
} |
function displayProductDetails(product) { |
// 更新DOM元素 |
document.getElementById('productTitle').textContent = product.name; |
document.getElementById('productPrice').textContent = `¥${product.price.toFixed(2)}`; |
document.getElementById('productImage').src = product.imageUrl; |
document.getElementById('productImage').alt = product.name; |
document.getElementById('productDescription').textContent = product.description; |
// 更新评分(如果有) |
const ratingElement = document.getElementById('productRating'); |
if (product.rating) { |
ratingElement.innerHTML = `评分: ${product.rating} ★`; |
} else { |
ratingElement.textContent = '暂无评分'; |
} |
// 更新库存状态 |
const stockElement = document.getElementById('productStock'); |
if (product.stock > 0) { |
stockElement.textContent = `库存: ${product.stock} 件`; |
stockElement.style.color = '#27ae60'; |
} else { |
stockElement.textContent = '缺货'; |
stockElement.style.color = '#e74c3c'; |
} |
// 显示商品容器 |
productContainer.style.display = 'flex'; |
// 添加购物车按钮事件 |
document.getElementById('addToCartBtn').addEventListener('click', () => { |
addToCart(product.id); |
}); |
} |
function showError(message) { |
errorElement.textContent = message; |
errorElement.style.display = 'block'; |
} |
function addToCart(productId) { |
// 这里可以添加实际的购物车逻辑 |
alert(`商品 ${productId} 已加入购物车!`); |
// 实际项目中可能是这样的: |
/* |
fetch('/api/cart', { |
method: 'POST', |
headers: { |
'Content-Type': 'application/json', |
}, |
body: JSON.stringify({ productId: productId, quantity: 1 }) |
}) |
.then(response => response.json()) |
.then(data => { |
alert('商品已成功加入购物车!'); |
}) |
.catch(error => { |
console.error('加入购物车失败:', error); |
alert('加入购物车失败,请稍后再试'); |
}); |
*/ |
} |
}); |
4. 模拟API响应
在实际开发中,你需要一个真实的API端点。为了测试,你可以使用以下模拟数据格式:
json
{ |
"id": 123, |
"name": "高端无线蓝牙耳机", |
"price": 399.99, |
"description": "这款高端无线蓝牙耳机采用最新蓝牙5.0技术,提供长达30小时的播放时间,降噪功能出色,音质清晰。", |
"imageUrl": "https://example.com/images/headphones.jpg", |
"rating": 4.7, |
"stock": 15, |
"category": "电子产品", |
"sku": "EL-WP-001" |
} |
5. 实际项目中的增强功能
在实际项目中,你可能还需要考虑:
- 错误处理增强:
- 处理网络错误
- 处理API返回的特定错误代码
- 添加重试机制
- 用户体验改进:
- 添加加载动画
- 实现防抖/节流(如果支持实时搜索)
- 添加商品图片轮播(如果有多张图片)
- 性能优化:
- 添加缓存机制
- 实现懒加载
- 使用Service Worker缓存API响应
- 安全性考虑:
- 验证API响应
- 处理敏感数据
- 实现CORS配置
- 状态管理:
- 对于复杂应用,考虑使用Redux或Context API管理状态
6. 使用Axios的替代方案
如果你更喜欢使用Axios而不是Fetch API,可以这样修改:
javascript
// 在HTML中添加Axios引用 |
// <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> |
// 替换fetch部分为: |
axios.get(apiUrl) |
.then(response => { |
displayProductDetails(response.data); |
}) |
.catch(error => { |
console.error('获取商品详情失败:', error); |
showError(`获取商品详情失败: ${error.message}`); |
}) |
.finally(() => { |
loadingElement.style.display = 'none'; |
}); |
这个实战演练展示了如何从API获取商品数据并在网页上展示的基本流程。你可以根据实际需求进行调整和扩展。