0612作业
编写一个专业实用的导航下拉菜单,用前端实现功能
链接 + 无序列表 + 事件监听 + 事件委托
html代码:主要练习无序列表和链接功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>下拉菜单</title>
</head>
<body>
<ul id="nav">
<li><a href="">首页</a></li>
<li><a href="">秒杀</a></li>
<li>
<a href="">优惠券</a>
<ul>
<li><a href="">满100减10</a></li>
<li><a href="">满500减200</a></li>
<li><a href="">满1000减450</a></li>
<li><a href="">满2000减600</a></li>
</ul>
</li>
<li>
<a href="">生鲜超市</a>
<ul>
<li><a href="">绿色蔬菜</a></li>
<li><a href="">饮料乳品</a></li>
<li><a href="">家禽肉类</a></li>
<li><a href="">生猛海鲜</a></li>
<li><a href="">水果干货</a></li>
</ul>
</li>
<li>
<a href="">海外购</a>
<ul>
<li><a href="">德国</a></li>
<li><a href="">英国</a></li>
<li><a href="">日本</a></li>
<li><a href="">荷兰</a></li>
<li><a href="">美国</a></li>
</ul>
</li>
<li>
<a href="">订单查询</a>
</li>
<li>
<a href="">地址管理</a>
</li>
<li>
<a href="">送货服务</a>
</li>
<li>
<a href="">用户登录</a>
</li>
</ul>
<script>
const nav = document.querySelectorAll("#nav>li");
nav.forEach(function (nav) {
// 鼠标移入时 :显示下拉菜单
nav.addEventListener("mouseover", showSubMenu);
// 鼠标移出时:隐藏下拉菜单
nav.addEventListener("mouseout", closeSubMenu);
});
// 显示下拉菜单
function showSubMenu(ev) {
// 当前这个菜单有无子菜单
console.log(ev.target);
if (ev.target.nextElementSibling != null) {
ev.target.nextElementSibling.style.display = "block";
}
}
// 隐藏下拉菜单
function closeSubMenu(ev) {
if (
ev.target.nodeName === "A" &&
ev.target.nextElementSibling != null
) {
ev.target.nextElementSibling.style.display = "none";
}
}
</script>
</body>
</html>
js代码主要代码逻辑和功能:
1.定位通过选择器命中ul中的li元素
document.querySelectorAll("#nav>li")
2.事件监听nav.addEventListener监听鼠标的移入和移出动作事件
nav.addEventListener("mouseover", showSubMenu);
nav.addEventListener("mouseout", closeSubMenu);
addEventListener(事件类型,事件方法,false/true)
事件触发阶段类型 | 特征 | 参数设置 |
---|---|---|
冒泡 | 由内向外传递 | addEventListener(事件类型,事件方法,false ),最后一个参数可省略,默认就是冒泡方法 |
捕获 | 由外向内传递 | addEventListener(事件类型,事件方法,true ) |
3.事件委托代码逻辑
用父类代理所有子元素及后代元素上的同名事件
代码中寻找a标签同级别的ul列表,移入时判断当前这个菜单有无子菜单ev.target.nextElementSibling != null
如果发现就显示菜单ev.target.nextElementSibling.style.display = "block";
移出时关闭显示,把display = "none"
设置回去
if ( ev.target.nodeName === "A" && ev.target.nextElementSibling != null)
判断语句要同时判断是否为<a>标签的同级兄弟元素以及是否有子菜单,只有同为真时才说明该下拉菜单是需要操作的,避免因冒泡造成的其他元素隐藏掉!!
其他要学习掌握的知识
ev.target
返回的是当前在这触发事件的元素,ev.currentTarget
返回的是绑定实践的是哪个元素。
CSS样式代码,通过link引入HTML中:
<style>
/* 元素样式初始化: 学到盒模型再详细介绍 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
/* color: rgba(255, 255, 255, 0.7); */
color: #bbb;
text-decoration: none;
}
#nav {
display: flex;
justify-content: space-around;
background-color: royalblue;
width: 100vw;
height: 50px;
line-height: 50px;
}
li {
list-style: none;
margin: 0 10px;
float: left;
}
#nav > li > a:hover {
color: white;
}
/* 将父级设置为子菜单的定位容器,即转为定位元素即可 */
#nav > li {
position: relative;
}
#nav > li > ul {
position: absolute;
top: 50px;
width: 180px;
border: 1px solid #aaa;
border-top: none;
}
#nav > li > ul > li a {
display: inline-block;
height: 50px;
color: #444;
}
ul.sub li:hover {
background-color: #eee;
}
/* 初始化时不要显示子菜单 */
#nav > li > ul {
display: none;
}
</style>
nav样式使用width: 100vw;
可以让nav部分自动随着页面自适应视口宽度display: flex;justify-content: space-around;
同时使用弹性布局导航栏整条填满分布更加美观