js实现三级菜单
实现三级菜单的JavaScript方法
使用HTML和CSS构建基础结构
创建嵌套的<ul>和<li>元素表示菜单层级,CSS设置初始隐藏状态:
<ul class="menu-level-1">
<li>
一级菜单
<ul class="menu-level-2">
<li>
二级菜单
<ul class="menu-level-3">
<li>三级菜单项1</li>
<li>三级菜单项2</li>
</ul>
</li>
</ul>
</li>
</ul>
<style>
.menu-level-2, .menu-level-3 {
display: none;
}
li:hover > ul {
display: block;
}
</style>
纯JavaScript事件驱动实现
通过事件监听实现交互控制:
document.querySelectorAll('.menu-level-1 > li').forEach(item => {
item.addEventListener('mouseenter', () => {
const level2 = item.querySelector('.menu-level-2');
if(level2) level2.style.display = 'block';
});
item.addEventListener('mouseleave', () => {
const level2 = item.querySelector('.menu-level-2');
if(level2) level2.style.display = 'none';
});
});
// 二级菜单项事件绑定同理
document.querySelectorAll('.menu-level-2 > li').forEach(item => {
item.addEventListener('mouseenter', () => {
const level3 = item.querySelector('.menu-level-3');
if(level3) level3.style.display = 'block';
});
item.addEventListener('mouseleave', () => {
const level3 = item.querySelector('.menu-level-3');
if(level3) level3.style.display = 'none';
});
});
递归函数实现动态生成
适用于动态数据场景:
function createMenu(container, data, level = 1) {
const ul = document.createElement('ul');
ul.className = `menu-level-${level}`;
data.forEach(item => {
const li = document.createElement('li');
li.textContent = item.text;
if(item.children) {
createMenu(li, item.children, level + 1);
li.addEventListener('click', (e) => {
e.stopPropagation();
const childMenu = li.querySelector('ul');
childMenu.style.display = childMenu.style.display === 'block' ? 'none' : 'block';
});
}
ul.appendChild(li);
});
container.appendChild(ul);
}
// 使用示例
const menuData = [
{
text: "一级菜单",
children: [
{
text: "二级菜单",
children: [
{ text: "三级菜单1" },
{ text: "三级菜单2" }
]
}
]
}
];
createMenu(document.getElementById('menu-container'), menuData);
动画效果增强体验
添加CSS过渡效果提升用户体验:
.menu-level-2, .menu-level-3 {
opacity: 0;
max-height: 0;
overflow: hidden;
transition: opacity 0.3s, max-height 0.3s;
}
li:hover > ul {
opacity: 1;
max-height: 500px;
}
移动端适配方案
针对触摸设备添加点击事件支持:
function setupMobileMenu() {
const menuItems = document.querySelectorAll('li');
menuItems.forEach(item => {
item.addEventListener('click', function(e) {
if(this.querySelector('ul')) {
e.preventDefault();
const subMenu = this.querySelector('ul');
subMenu.style.display = subMenu.style.display === 'block' ? 'none' : 'block';
}
});
});
}
注意事项
- 事件委托优化性能,避免为每个菜单项单独绑定事件
- 使用
position: absolute定位子菜单防止页面布局抖动 - 添加
aria-expanded属性增强可访问性 - 考虑使用
requestAnimationFrame优化动画性能
以上方案可根据实际需求组合使用,纯CSS方案适合简单场景,JavaScript方案提供更精细的控制,递归函数适合动态数据加载场景。







