![](https://i-blog.csdnimg.cn/blog_migrate/7c6f1ed6f55cf57f2d7131041f691cec.png)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
ul{
list-style: none;
}
.box {
width: 500px;
}
.box span {
display: block;
height: 35px;
line-height: 35px;
cursor: pointer;
}
.box span.close:before {
content: "+";
font-size: 20px;
font-weight: bold;
color: red;
}
.box span.open:before {
content: "-";
font-size: 30px;
font-weight: bold;
color: red;
}
</style>
</head>
<body>
<ul class="box" id="box">
<li><span>第一级菜单</span>
<ul>
<li><span>第二级菜单</span>
<ul>
<li><span>第三级菜单</span>
<ul>
<li><span>第四级菜单</span></li>
<li><span>第四级菜单</span></li>
</ul>
</li>
<li><span>第三级菜单</span></li>
<li><span>第三级菜单</span></li>
<li><span>第三级菜单</span></li>
</ul>
</li>
<li><span>第二级菜单</span>
<ul>
<li><span>第三级菜单</span></li>
<li><span>第三级菜单</span></li>
<li><span>第三级菜单</span></li>
<li><span>第三级菜单</span></li>
</ul>
</li>
<li><span>第二级菜单</span>
</li>
<li><span>第二级菜单</span></li>
</ul>
</li>
<li><span>第一级菜单</span></li>
<li><span>第一级菜单</span></li>
<li><span>第一级菜单</span></li>
</ul>
<script>
// 1、获取所有的span元素
let spans = document.getElementsByTagName('span');
// 2、判断一下当前的span有没有兄弟元素:如果有那它里面就有东西,这样就让当前的span加上close类名,并且让它的兄弟元素默认隐藏;否则加上open类名
//这个过程为每一个span前面添加合适的标识:‘+’/‘-’
for(let i=0;i<spans.length;i++){
let cur=spans[i];//当前span(当前span要么是独生子,要么是第一个孩子)
let next=cur.nextElementSibling;//当前span的下一个兄弟元素
//如果当前span的下一个兄弟元素存在,说明里面有东西,span可以打开
if(cur.nextElementSibling){
cur.classList.add('close');
next.style.display='none';
}else{
cur.classList.add('open');
}
}
//菜单盒子绑定点击事件,由于存在冒泡机制,无论点击菜单盒子的哪个位置都会触发此点击事件,根据事件对象的target目标源来确定当前点击的是哪个span
box.onclick=function(e){
let cur=e.target;//当前点击的元素
//如果点击的元素不是span,那就什么都不做
if(cur.nodeName!=='SPAN'){
return;
}
let next=cur.nextElementSibling;//当前span的下一个兄弟元素
//如果当前next有值,那就可以进行打开和关闭的操作;如果当前next没有值,那就什么都不做
if(next){
// if(cur.classList.contains('close')){}
//判断一下当前的span有没有close类名:如果有,那就是想要展开;如果没有,那就是想要关闭
if(cur.className.includes('close')){
cur.className='open';//把类名变成展开
next.style.display='block';//让当前span下的ul显示
}else{
cur.className='close';//把类名变成关闭
next.style.display='none';//让当前span下的ul隐藏
let uls=next.getElementsByTagName('ul');//获取当前span下一个兄弟元素中所有的ul
for(let i=0;i<uls.length;i++){
uls[i].style.display='none';//隐藏ul
uls[i].previousElementSibling.className='close';//将ul前面span的类名变成关闭
}
}
}
};
</script>
</body>
</html>