如何实现以下的导航栏下拉菜单的效果
实现思路
(1) 用html与css渲染出下拉菜单(html 主要使用ul,li标签来实现)
(2)用点击事件去绑定所需要的dom元素,实现点击就可以下拉菜单
(3)在考虑点击下一个dom元素,使前一个下拉菜单消失
实现方法
1.用javaScript与jQuery实现
(1)html 的代码如下
1 <!-- 导航栏 --> 2 <div class="top"> 3 <ul class="header-container"> 4 <li class='out'> 5 报名申请 6 <ul class="drop"> 7 <li>考级报名</li> 8 <li>创新创业报名</li> 9 </ul> 10 </li> 11 <li class='out'> 12 信息维护 13 <ul class="drop"> 14 <li>学生个人信息维护</li> 15 <li>专业方向确认</li> 16 </ul> 17 </li> 18 <li class='out'> 19 选课 20 <ul class="drop"> 21 <li>学生课表查询</li> 22 </ul> 23 </li> 24 <li class='out'> 25 信息查询 26 <ul class="drop"> 27 <li>查询个人信息</li> 28 </ul> 29 </li> 30 <li class='out'> 31 教学评价 32 <ul class="drop"> 33 <li>问卷调查</li> 34 </ul> 35 </li> 36 </ul> 37 </div>
(2)css的代码如下
1 html,body{ 2 margin:0; 3 width: 100%; 4 height:100%; 5 } 6 .top{ 7 width: 100%; 8 height: 60px; 9 background: linear-gradient(60deg,#e364f4, #e151f4); 10 display: flex; 11 justify-content: center; 12 align-items: center 13 /* background:linear-gradient(red 0%, orange 25%,green 75%, blue 100%); */ 14 } 15 .header-container{ 16 display: flex; 17 /* border: 1px solid #fff; */ 18 height: 100%; 19 justify-content: space-between; 20 align-items: center; 21 min-width: 800px; 22 max-width: 1200px; 23 margin: 0px; 24 list-style: none; 25 color: #fff; 26 padding: 0; 27 cursor: pointer; 28 transition: all .28s; 29 } 30 .header-container li{ 31 padding:0 20px 0 20px; 32 height: 100%; 33 line-height:60px; 34 position: relative; 35 } 36 37 li:hover{ 38 background:#e0dfdf ; 39 color:rgb(51, 49, 49) 40 } 41 li:active{ 42 background:#c3c3c3; 43 color:black 44 } 45 .drop{ 46 position: absolute; 47 width: 200px; 48 color:#000; 49 list-style: none; /* 去掉ul的样式 */ 50 margin:0; 51 padding:0; 52 background: #fff; 53 border: 1px solid #E9E8F0; 54 display: none; 55 } 56 .show{ 57 display: block; 58 } 59 .drop li{ 60 font-size: 14px; 61 line-height: 40px; 62 position: relative; 63 }
上面的下拉菜单的出现与消失,主要是通过控制 <ul class="drop"></ul> class类名的增加与移除
(3) javaScript的代码如下
1 /** 2 javascript 实现 3 */ 4 5 var outLi=document.querySelectorAll('.out'); 6 7 // 存储前一次点击的序号的数组 8 var param=[]; 9 10 // 为第一层ul的每一项li的index绑定一个值 11 for(let i=0;i<outLi.length;i++){ 12 outLi[i].index=i; 13 } 14 // 为第一层ul的每一项li的绑定监听事件 15 for(let i=0;i<outLi.length;i++){ 16 // 监听器 17 outLi[i].addEventListener('click',function(){ 18 // 阻止父元素的click事件 19 event.stopPropagation(); 20 if(param.length===1){ 21 // 获取前一项的序号 22 var j=param[0]; 23 if(j===this.index){ 24 outLi[j].getElementsByClassName('drop')[0].classList.remove('show'); 25 // 清空数组 26 param=[]; 27 return 28 } 29 outLi[j].getElementsByClassName('drop')[0].classList.remove('show'); 30 // 清空数组 31 param=[]; 32 } 33 34 this.getElementsByClassName('drop')[0].classList.add('show') 35 36 param.push(this.index) 37 38 }) 39 } 40 41 document.getElementsByTagName('body')[0].addEventListener("click",function(){ 42 if(param.length!==0){ 43 var j=param[0]; 44 outLi[j].getElementsByClassName('drop')[0].classList.remove('show'); 45 param=[]; 46 47 } 48 })
下面这段代码主要思路是,
通过param这个数组来判断鼠标点击当前的元素之前的有没有点击其他在这个导航栏的其他元素
如果有(数组的长度为1,表示数组有一项),假设点击的项的index与数组存储的值一样,则代表元素两次点击同一项(默认为取消下拉菜单操作,不会再出现下来菜单,直接return,不会再执行下面的操作);
反之,不是同个值,则通过param的数组去取消下拉并清空数组,而当前click则出现下拉,并且当前的index进栈
if(param.length===1){ // 获取前一项的序号 var j=param[0]; if(j===this.index){ outLi[j].getElementsByClassName('drop')[0].classList.remove('show'); // 清空数组 param=[]; return } outLi[j].getElementsByClassName('drop')[0].classList.remove('show'); // 清空数组 param=[]; } this.getElementsByClassName('drop')[0].classList.add('show') param.push(this.index)
注:this.getElementsByClassName('drop')[0].classList.add('show')中涉及到一个this的指向问题,在this的官方文档中指出,若this作为一个dom事件处理的函数,this指向触发事件的元素。
从这可以看出 点击事件触发的是outLi[i]的元素,所以this指向的元素是outLi[i]。
如果你想查询更多有关this的问题,请访问 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this
(4) jQuery的代码如下
1 /** 2 jQuery 实现 3 */ 4 var $param=[] 5 6 $('.out').click(function(event){ 7 event.stopPropagation(); 8 var $index=$(this).index(); 9 if($param.length===1){ 10 if($param[0]===$index){ 11 $('.drop').eq($param[0]).removeClass('show'); 12 $param=[]; 13 return; 14 } 15 $('.drop').eq($param[0]).removeClass('show'); 16 $param=[]; 17 } 18 19 $('.drop').eq($index).addClass('show'); 20 $param.push($index) 21 // console.log($index) 22 console.log($param) 23 }) 24 25 26 27 $('body').click(function(){ 28 $show= $('.out').find('.show'); 29 $show.removeClass('show'); 30 31 })
由上可以看出,jQuery方法看上去比javaScript方便许多,主要是因为jQuery是javaScript的一个库,所以用原生dom封装了许多便利的方法
例如:javaScript需要我们自己给每一项li的lndex赋值,而jQuery封装了index()方法,可以指定元素相对于其他指定元素的index值。还一个是eq() 放回带有被选元素的指定索引值的元素
2. 用vue实现(css代码如上)
1 <template> 2 <div class="home" @click="cancel"> 3 <!-- 导航栏 --> 4 <div class="top"> 5 <ul class="header-container"> 6 <li class='out' v-for="(item,index) in header" :key="index" @click.stop="drop(index)"> 7 {{item.tabTitle}} 8 <ul class="drop" > 9 <li v-for="(tip,index) in item.drop" :key="index" @click="jump(item.index,index)">{{tip}}</li> 10 </ul> 11 </li> 12 </ul> 13 </div> 14 </div> 15 </template>
js代码部分
1 <script> 2 export default { 3 name: 'Home', 4 data(){ 5 return { 6 header:[ 7 { 8 tabTitle:"报名申请", 9 drop:['考证报名','创新创业报名'] 10 }, 11 { 12 tabTitle:"信息维护", 13 drop:['学生个人信息维护','专业方向确认'] 14 }, 15 { 16 tabTitle:"选课", 17 drop:['学生课表查询'] 18 }, 19 { 20 tabTitle:"信息查询", 21 drop:['查询个人信息'] 22 }, 23 { 24 tabTitle:"教学评价", 25 drop:['问卷调查'] 26 } 27 ], 28 // 存储前一个的数组 29 parmas:[] 30 } 31 }, 32 methods:{ 33 // 下拉菜单显示 34 drop(index){ 35 var out=document.getElementsByClassName('out')[index]; 36 if(this.parmas.length===1){ 37 document.getElementsByClassName('out')[this.parmas[0]] 38 .getElementsByClassName('drop')[0].classList.remove('show'); 39 this.parmas=[] 40 } 41 out.getElementsByClassName('drop')[0].classList.add('show'); 42 this.parmas.push(index); 43 console.log(this.parmas) 44 }, 45 jump(itemIndex,TipIndex){ 46 console.log(itemIndex) 47 console.log(TipIndex) 48 }, 49 // 全局点击取消下拉 50 cancel(){ 51 if(this.parmas.length!==0){ 52 document.getElementsByClassName('out')[this.parmas[0]] 53 .getElementsByClassName('drop')[0].classList.remove('show'); 54 } 55 } 56 } 57 } 58 </script>
实现方法的代码与javaScript基本上一致的,区别在与html的渲染,采用的是vue所拥有的属性,v-for渲染出来。
以上是作为小白的我实现下拉菜单,如果大家有更好的想法,可以评论分享下哈哈哈啊哈哈