当前位置: 首页 > article >正文

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

结语

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


http://www.kler.cn/a/419862.html

相关文章:

  • VSCode如何关闭Vite项目本地自启动
  • 【Spring】Spring IOCDI:架构旋律中的“依赖交响”与“控制华章”
  • 【Linux课程学习】:站在文件系统之上理解:软硬链接,软硬链接的区别
  • 项目搭建+添加
  • 性能监控系统Prometheus、Node-exporter与Grafana部署详解搭建
  • Gazebo插件相机传感器(可订阅/camera/image_raw话题)
  • leetcode530:二叉搜索树的最小绝对值差
  • GitHub Copilot革命性更新:整合顶尖AI模型,如何重塑开发体验?
  • 用 React 编写一个笔记应用程序
  • SQL优化与性能——C++与SQL性能优化
  • 重学设计模式-建造者模式
  • 题海拾贝——生成元(Digit Generator,ACM/ICPC SEOUL 2005,UVa1583)
  • 15.三数之和 python
  • 深度学习模型:门控循环单元(GRU)详解
  • Web基础
  • java中的运算符
  • Elasticsearch面试内容整理-面试注意事项
  • Python 深度学习框架之Keras库详解
  • AI在线免费视频工具4:AI视频编辑ai-video-composer
  • 2024.12.2工作复盘
  • Ubuntu20.04安装NVIDIA显卡驱动
  • parallelStream并行流使用踩坑,集合安全
  • 4399 Android面试题及参考答案
  • [382]基于springboot的辽B代驾管理系统
  • 论文阅读:Deep divergence-based approach to clustering
  • 【HarmonyOS】自定义相机拍照和录像 (二)之录像