基于JavaScript实现城市自行车搜索功能开发需求
城市自行车搜索功能实现方案
以下是满足需求的完整实现代码,包含搜索输入框、Bootstrap加载动画,以及基于Fetch API的动态数据渲染逻辑:
1. 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> <!-- 引入Bootstrap CSS用于加载动画 --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="styles.css"> </head> <body> <div class="page-container"> <h2>城市自行车搜索</h2> <div class="search-bar"> <input type="text" id="bike-input" placeholder="输入自行车名称搜索..." /> <button id="search-trigger">搜索</button> </div> <!-- Bootstrap加载动画 --> <div id="loader" class="spinner-border text-primary d-none" role="status"> <span class="visually-hidden">加载中...</span> </div> <!-- 搜索结果容器 --> <div id="search-results" class="results-wrapper"></div> </div> <script src="script.js"></script> </body> </html>
2. CSS 样式
.page-container { max-width: 700px; margin: 3rem auto; padding: 0 1.5rem; } .search-bar { display: flex; gap: 0.8rem; margin: 2rem 0; } #bike-input { flex: 1; padding: 0.8rem; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 1rem; } #search-trigger { padding: 0.8rem 1.6rem; background-color: #0d6efd; color: #fff; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; } #search-trigger:hover { background-color: #0b5ed7; } .results-wrapper { margin-top: 2rem; display: grid; gap: 1.2rem; } .bike-item { padding: 1.4rem; border: 1px solid #f0f0f0; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); } .bike-title { font-size: 1.2rem; font-weight: 600; margin-bottom: 0.5rem; } .bike-location { color: #666; font-size: 0.95rem; } #loader { display: block; margin: 2rem auto; } .d-none { display: none !important; }
3. JavaScript 功能逻辑
const searchInput = document.getElementById('bike-input'); const searchBtn = document.getElementById('search-trigger'); const loader = document.getElementById('loader'); const resultsContainer = document.getElementById('search-results'); // 页面加载时默认拉取全部自行车数据 document.addEventListener('DOMContentLoaded', () => { fetchBikeData(''); }); // 绑定搜索按钮点击事件 searchBtn.addEventListener('click', () => { const searchQuery = searchInput.value.trim(); fetchBikeData(searchQuery); }); // 绑定回车键搜索事件 searchInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { const searchQuery = searchInput.value.trim(); fetchBikeData(searchQuery); } }); // 核心数据请求与渲染函数 function fetchBikeData(query) { // 显示加载动画,清空旧结果 loader.classList.remove('d-none'); resultsContainer.innerHTML = ''; const apiEndpoint = `https://apis.ccbp.in/city-bikes?bike-name=${encodeURIComponent(query)}`; fetch(apiEndpoint) .then(response => { if (!response.ok) throw new Error('数据请求失败'); return response.json(); }) .then(data => { loader.classList.add('d-none'); if (data.bikes.length === 0) { const emptyTip = document.createElement('div'); emptyTip.textContent = '未找到匹配的自行车信息'; emptyTip.style.textAlign = 'center'; emptyTip.style.padding = '2rem'; resultsContainer.appendChild(emptyTip); return; } // 动态生成结果元素并添加到容器 data.bikes.forEach(bike => { const bikeCard = document.createElement('div'); bikeCard.className = 'bike-item'; const nameEl = document.createElement('div'); nameEl.className = 'bike-title'; nameEl.textContent = bike.name; const cityEl = document.createElement('div'); cityEl.className = 'bike-location'; cityEl.textContent = `所在城市:${bike.city}`; bikeCard.appendChild(nameEl); bikeCard.appendChild(cityEl); resultsContainer.appendChild(bikeCard); }); }) .catch(error => { loader.classList.add('d-none'); const errorTip = document.createElement('div'); errorTip.textContent = `加载出错:${error.message}`; errorTip.style.color = '#dc3545'; errorTip.style.textAlign = 'center'; errorTip.style.padding = '2rem'; resultsContainer.appendChild(errorTip); console.error('请求异常:', error); }); }
关键说明
- 页面加载时自动调用接口获取全部自行车数据
- 支持输入框关键词搜索及回车键快捷提交
- 加载状态使用Bootstrap官方Spinner组件实现
- 所有结果元素均为动态创建,仅作为
search-results容器的子元素插入 - 包含空结果、请求失败等异常场景的提示处理
内容的提问来源于stack exchange,提问作者Lohitha
相关产品推荐
相关产品推荐

