You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:15:54