【JavaScript】下拉框的实现
什么是下拉框
鼠标放到黑色盒子上才会显示下拉框中的 内容,红色盒子是显示文本内容。
蓝色盒子对外隐藏,鼠标放上去会将黑色盒子高度扩大。
JavaScript 获取元素的高度
使用querySelector或者querySelectorAll获取元素,使用循环进行重复元素的选择,对元素的height属性进行修改。
var ul_list = document.querySelectorAll("ul")
for(var k =0;k<ul_list.length;k++){
ul_list[k].style.height=0;
}
事件传播机制
事件的发生分为两个阶段:捕获阶段和冒泡阶段,两个阶段只能二选一,即选择其中一个阶段发生。
事件传播机制想要发生,需要嵌套的元素且绑定相同的事件。
捕获阶段是由父级元素向下到触点元素,此阶段触点元素的父级元素不会执行相同的事件,捕获阶段可以看成顺着父级元素向下寻找目标触点元素的阶段,找到触点元素后事件发生,接着进入冒泡阶段。
冒泡阶段是由触点元素事件发生向父级元素传递事件,此阶段中,触点元素事件发生后,向上传递,如果父级元素中没有相同的操作,跳过该级元素,继续向上寻找。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件传播机制</title>
<style>
.container{
width: 500px;
height: 500px;
background: aliceblue;
margin: auto;
display: flex;
justify-content: center;
}
.container .father{
width: 300px;
height: 300px;
background: red;
margin: auto;
display: flex;
justify-content: center;
}
.container .father .child{
width: 100px;
height: 100px;
background: yellow;
margin: auto;
}
</style>
</head>
<body>
<!-- 事件传播机制想要发生,需要嵌套的元素且绑定相同的事件 -->
<h1>body</h1>
<div class="container">
<h2>container</h2>
<div class="father">
<h3>father</h3>
<div class="child">
<h4>child</h4>
</div>
</div>
</div>
<script>
var body = document.querySelector("body")
var container = document.querySelector(".container")
var father = document.querySelector(".father")
var child = document.querySelector(".child")
body.addEventListener("click",function(){
console.log("俺是body")
})
container.addEventListener("click",function(){
console.log("俺是container")
})
father.addEventListener("click",function(){
console.log("俺是father")
})
child.addEventListener("click",function(){
console.log("俺是child")
})
</script>
</body>
</html>
对上述实现事件传播机制的代码,运行示例:
可以看出,对子级元素进行事件触发时,会逐级向上触发父级元素的同类事件,即在控制台输出“俺是XXX”的内容。
可以使用stopPropagation()方法来阻止事件传播。容易理解的是,在哪级元素调用该方法,事件传播就在哪级元素上停止。
<script>
var body = document.querySelector("body")
var container = document.querySelector(".container")
var father = document.querySelector(".father")
var child = document.querySelector(".child")
body.addEventListener("click",function(){
console.log("俺是body")
})
container.addEventListener("click",function(){
console.log("俺是container")
})
father.addEventListener("click",function(){
console.log("俺是father")
e.stopPropagation()
})
child.addEventListener("click",function(){
console.log("俺是child")
})
</script>
只在father上添加事件阻止,那么在child的事件触发时,father的事件也会被执行,但到此为止。对container的事件,body的事件也会被触发,因为container没有调用stopPropagation。
下拉框的实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>下拉框</title>
<!-- defer 针对外引结构才会起效果
内嵌不起效果 -->
<script src="下拉框.js" defer></script>
<!-- 使用window.onload进行延迟使用事件 -->
<!-- <script>
window.onload = function(){
}
</script> -->
<style>
/* ease表示又慢到快 */
*{
padding: 0;
margin: 0;
/* 复合属性 */
transition: all 1s ease;
}
li{
list-style:none;
}
a{
text-decoration: none;
}
.container{
width: 80%;
margin: 20px auto;
background: red;
display: flex;
justify-content: space-around;
position: relative;
}
.container a{
padding: 10px;
display:block;
color:#fff;
background: red;
}
.container a:hover{
background:#fff;
color: red;
}
.container ul{
position: absolute;
/* display: none; */
height: 0;
overflow: hidden;
background: yellow;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<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>
</div>
<div class="item">
<a href="#">机构设置</a>
<ul>
<li><a href="">学校章程</a></li>
<li><a href="">历任领导</a></li>
<li><a href="">现任领导</a></li>
</ul>
</div>
<div class="item">
<a href="#">国际合作</a>
<ul>
<li><a href="">学校简介</a></li>
<li><a href="">现任领导</a></li>
<li><a href="">学校简介</a></li>
</ul>
</div>
<div class="item">
<a href="#">学科专业</a>
<ul>
<li><a href="">学校章程</a></li>
<li><a href="">历任领导</a></li>
<li><a href="">现任领导</a></li>
<li><a href="">学校简介</a></li>
</ul>
</div>
<div class="item">
<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>
<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>
</div>
<div class="item">
<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>
<li><a href="">历任领导</a></li>
<li><a href="">现任领导</a></li>
<li><a href="">学校简介</a></li>
</ul>
</div>
</div>
</body>
</html>
获取所有的目标元素
使用getElementsByClassName获取页面中所有class属性为item的元素,并返回一个类数组。
var items= document.getElementsByClassName("item")
console.log(items)
遍历获取到的元素并添加点击事件
遍历items集合,为每个item元素绑定onclick事件。stopPropagation阻止事件冒泡,防止对item元素中的点击事件传递到document上的全局点击事件。
for(var i = 0;i<items.length;i++){
console.dir(items[i])
items[i].onclick = function(e){
e.stopPropagation()
...
}
点击事件的实现
获取页面中所有的ul元素,遍历这些元素,将style.height设置为0,实现隐藏或收起效果。根据html中的item结构,ul和标题是不同的标签,选择ul时不会对菜单中的标题修改。
var ul_list = document.querySelectorAll("ul")
for(var k =0;k<ul_list.length;k++){
ul_list[k].style.height=0;
}
获取当前被点击的item元素中的a标签,遍历这些a标签,累加他们的高度,将得到的结果设置为ul展开的高度。
var arr = this.querySelectorAll("ul a")
var num =0
for(var j =0;j<arr.length;j++){
num+=arr[j].clientHeight
console.log(arr[j].clientHeight)
}
console.log(num)
this.querySelector("ul").style.height = num + "px"
点击空白处收起ul
为整个文档绑定点击事件,当页面的任意部位被点击时,将所有的ul的高度设置为0,实现收起的效果,要添加阻止事件冒泡,避免干扰其他事件。
document.onclick = function(e){
e.stopPropagation()
// 让所有的ul高度都设成0
var ul_list = document.querySelectorAll("ul")
for(var k =0;k<ul_list.length;k++){
ul_list[k].style.height=0;
}
}
完整代码
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>下拉框</title>
<!-- defer 针对外引结构才会起效果
内嵌不起效果 -->
<script src="下拉框.js" defer></script>
<!-- 使用window.onload进行延迟使用事件 -->
<!-- <script>
window.onload = function(){
}
</script> -->
<style>
/* ease表示又慢到快 */
*{
padding: 0;
margin: 0;
/* 复合属性 */
transition: all 1s ease;
}
li{
list-style:none;
}
a{
text-decoration: none;
}
.container{
width: 80%;
margin: 20px auto;
background: red;
display: flex;
justify-content: space-around;
position: relative;
}
.container a{
padding: 10px;
display:block;
color:#fff;
background: red;
}
.container a:hover{
background:#fff;
color: red;
}
.container ul{
position: absolute;
/* display: none; */
height: 0;
overflow: hidden;
background: yellow;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<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>
</div>
<div class="item">
<a href="#">机构设置</a>
<ul>
<li><a href="">学校章程</a></li>
<li><a href="">历任领导</a></li>
<li><a href="">现任领导</a></li>
</ul>
</div>
<div class="item">
<a href="#">国际合作</a>
<ul>
<li><a href="">学校简介</a></li>
<li><a href="">现任领导</a></li>
<li><a href="">学校简介</a></li>
</ul>
</div>
<div class="item">
<a href="#">学科专业</a>
<ul>
<li><a href="">学校章程</a></li>
<li><a href="">历任领导</a></li>
<li><a href="">现任领导</a></li>
<li><a href="">学校简介</a></li>
</ul>
</div>
<div class="item">
<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>
<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>
</div>
<div class="item">
<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>
<li><a href="">历任领导</a></li>
<li><a href="">现任领导</a></li>
<li><a href="">学校简介</a></li>
</ul>
</div>
</div>
</body>
</html>
JavaScript:
var items= document.getElementsByClassName("item")
console.log(items)
for(var i = 0;i<items.length;i++){
console.dir(items[i])
items[i].onclick = function(e){
e.stopPropagation()
// 让所有的ul高度都设成0
var ul_list = document.querySelectorAll("ul")
for(var k =0;k<ul_list.length;k++){
ul_list[k].style.height=0;
}
//唯独让被点击的ul有高度
var arr = this.querySelectorAll("ul a")
var num =0
for(var j =0;j<arr.length;j++){
num+=arr[j].clientHeight
console.log(arr[j].clientHeight)
}
console.log(num)
this.querySelector("ul").style.height = num + "px"
}
}
document.onclick = function(e){
e.stopPropagation()
// 让所有的ul高度都设成0
var ul_list = document.querySelectorAll("ul")
for(var k =0;k<ul_list.length;k++){
ul_list[k].style.height=0;
}
}
结语
浏览网页时,发现还可以添加鼠标离开就收起的效果,比较简单哈。还有下拉框的动画快慢也可以进行调整,这里仅做实现,不进行详细展开。