
本文介绍如何使用 html、bootstrap、javascript 和 jquery 构建两级分类导航:点击顶部主分类显示其下属父卡片,再点击任一父卡片动态加载并展示其子卡片,全程无需页面刷新。
本文介绍如何使用 html、bootstrap、javascript 和 jquery 构建两级分类导航:点击顶部主分类显示其下属父卡片,再点击任一父卡片动态加载并展示其子卡片,全程无需页面刷新。
要实现“点击主分类 → 显示对应父卡片 → 再点击父卡片 → 展开其子卡片”这一层级式交互,推荐采用结构化数据驱动 + Bootstrap 折叠(Collapse)组件 + 轻量级 jQuery 事件控制的方案。该方案语义清晰、兼容性好、易于维护,且完全契合 Bootstrap 5+ 的设计范式。
✅ 推荐实现结构(HTML + Bootstrap 5)
<!-- 1. 顶部主分类导航 -->
<nav class="navbar navbar-expand-lg bg-light"><div class="container-fluid">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#" data-main="korean">Korean Cars</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-main="german">German Cars</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-main="japanese">Japanese Cars</a>
</li>
</ul>
</div>
</nav><!-- 2. 父卡片容器(初始隐藏) --><div id="parent-cards" class="container mt-4 d-none">
<h4 id="main-category-title"></h4>
<div class="row" id="parent-card-list"></div>
</div>
<!-- 3. 子卡片容器(动态插入) -->
<div id="child-cards" class="container mt-4 d-none">
<h5 id="parent-card-title"></h5>
<div class="row" id="child-card-list"></div>
</div>
✅ 数据组织建议(JS 对象模拟)
const categoryData = {
korean: {
title: "Korean Cars",
parents: [
{
id: "hyundai",
name: "Hyundai",
children: ["Elantra", "Sonata", "Tucson", "Kona"]
},
{
id: "kia",
name: "Kia",
children: ["Sorento", "Sportage", "Telluride", "Forte"]
}
]
},
german: {
title: "German Cars",
parents: [
{ id: "bmw", name: "BMW", children: ["X3", "3 Series", "X5"] },
{ id: "audi", name: "Audi", children: ["A4", "Q5", "A6"] }
]
}
};
✅ 核心交互逻辑(jQuery)
$(document).ready(function () {
// 点击主分类:显示对应父卡片
$('[data-main]').on('click', function (e) {
e.preventDefault();
const mainKey = $(this).data('main');
const data = categoryData[mainKey];
if (!data) return;
// 更新标题 & 清空旧内容
$('#main-category-title').text(data.title);
$('#parent-card-list').empty();
// 渲染父卡片
data.parents.forEach(parent => {
const card = `
<div class="col-md-4 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">${parent.name}</h5>
<a href="#" class="btn btn-sm btn-primary show-children" data-parent="${parent.id}">View Models</a>
</div>
</div>
</div>
`;
$('#parent-card-list').append(card);
});
// 显示父卡片区,隐藏子卡片区
$('#parent-cards').removeClass('d-none');
$('#child-cards').addClass('d-none');
});
// 点击父卡片按钮:展开子卡片
$(document).on('click', '.show-children', function (e) {
e.preventDefault();
const parentId = $(this).data('parent');
const mainKey = $('[data-main].active').data('main') || 'korean';
const parent = categoryData[mainKey].parents.find(p => p.id === parentId);
if (!parent) return;
// 渲染子卡片网格
const childHtml = parent.children.map(model => `
<div class="col-md-3 mb-2">
<div class="badge bg-secondary py-2 px-3">${model}</div>
</div>
`).join('');
$('#parent-card-title').text(`${parent.name} Models`);
$('#child-card-list').html(childHtml);
// 切换视图
$('#child-cards').removeClass('d-none');
$('#parent-cards').addClass('d-none');
});
});
⚠️ 关键注意事项
- 不要用 style.display = "none/block" 手动操作:直接操作内联样式会覆盖 Bootstrap 响应式类,破坏移动端适配;应优先使用 .d-none / .d-block 等工具类。
- 事件委托必须使用 $(document).on():因为父卡片是动态生成的,直接绑定 .on('click', ...) 无效。
- 避免重复初始化:每次切换主分类前务必清空 #parent-card-list 和 #child-card-list,防止内容累积。
- 可扩展性增强建议:后续可将 categoryData 替换为 AJAX 请求(如 /api/categories/korean),实现服务端动态加载,提升首屏性能与 SEO 可见性。
通过以上结构,你将获得一个语义清晰、响应迅速、符合现代前端实践的两级分类导航系统——既满足基础交互需求,也为未来接入 CMS 或 API 预留了标准接口。











