【JavaScript】下拉框的实现

什么是下拉框

鼠标放到黑色盒子上才会显示下拉框中的 内容,红色盒子是显示文本内容。

蓝色盒子对外隐藏,鼠标放上去会将黑色盒子高度扩大。

JavaScript 获取元素的高度

使用querySelector或者querySelectorAll获取元素,使用循环进行重复元素的选择,对元素的height属性进行修改。

javascript 复制代码
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>
    <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()方法来阻止事件传播。容易理解的是,在哪级元素调用该方法,事件传播就在哪级元素上停止。

javascript 复制代码
    <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。

下拉框的实现

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>
获取所有的目标元素

使用getElementsByClassName获取页面中所有class属性为item的元素,并返回一个类数组。

javascript 复制代码
var items= document.getElementsByClassName("item")
console.log(items)
遍历获取到的元素并添加点击事件

遍历items集合,为每个item元素绑定onclick事件。stopPropagation阻止事件冒泡,防止对item元素中的点击事件传递到document上的全局点击事件。

javascript 复制代码
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时不会对菜单中的标题修改。

javascript 复制代码
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展开的高度。

javascript 复制代码
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,实现收起的效果,要添加阻止事件冒泡,避免干扰其他事件。

javascript 复制代码
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:

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:

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;
    }
}

结语

浏览网页时,发现还可以添加鼠标离开就收起的效果,比较简单哈。还有下拉框的动画快慢也可以进行调整,这里仅做实现,不进行详细展开。

相关推荐
cnsxjean1 小时前
Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架
javascript·vue.js·ui·前端框架·npm
web组态软件1 小时前
BY组态-低代码web可视化组件
前端·低代码
react_in1 小时前
webpack 题目
前端·webpack
MarisolHu1 小时前
前端学习笔记-Vue篇-02
前端·vue.js·笔记·学习
学前端的小朱1 小时前
Webpack的基础配置
前端·webpack·node.js
小小优化师 anny2 小时前
JS +CSS @keyframes fadeInUp 来定义载入动画
javascript·css·css3
小周同学_丶2 小时前
解决el-select数据量过大的3种方法
前端·vue.js·elementui
先知demons3 小时前
uniapp开发微信小程序笔记10-触底加载
前端·笔记·微信小程序·小程序·uni-app
每一天,每一步3 小时前
react antd不在form表单中提交表单数据,而是点查询按钮时才将form表单数据和其他查询条件一起触发一次查询,避免重复触发请求
前端·javascript·react.js
NoneCoder3 小时前
HTML5系列(9)-- Web Components
前端·html·html5