js如何实现点击空白处让元素消失.

项目中自己写下拉框时,常常会有这样的需求;
点击下拉框时,下拉框里面的内容显示;
点击除了下框之外的其他地方,下拉框要关闭;
我是这样写的

 <div class="select-wrap">
        <div class="select-span">
            <span>选择一个</span>
        </div>
        <ul class="select-list">
            <li>1111111111</li>
            <li>2222222222</li>
            <li>3333333333</li>
        </ul>
    </div>
    //点击打开点击关闭
    $(".select-wrap .select-span").click(function(){
        $(".select-wrap .select-list").slideToggle();
    });
    //下拉框里面的选中事件
    $(".select-wrap .select-list li").on('click', function (e) {
        e.stopPropagation();
        $(this).parents('.select-wrap').find('span').html($(this).html());
        $(this).parents('.select-wrap').find('.select-list').slideUp();
        $(".select-wrap1 .select-list").slideDown('fast', 'swing');
    })
    //点击空白处,下拉框消失的代码
    $(document).click(function(e) {
        var target = $(e.target);
        if(target.closest(".select-wrap").length == 0) {
           $(".select-wrap .select-list").slideUp();  
        };
    });

上面这样写看着没什么问题,但是如果有两个一样的下拉框,(一摸一样,包括类名,通过循环创建的,不确定会有多少个这样的下拉框)

    <div class="select-wrap">
        <div class="select-span">
            <span>选择一个</span>
        </div>
        <ul class="select-list">
            <li>1111111111</li>
            <li>2222222222</li>
            <li>3333333333</li>
        </ul>
    </div>
    <div class="select-wrap">
        <div class="select-span">
            <span>选择一个</span>
        </div>
        <ul class="select-list">
            <li>1111111111</li>
            <li>2222222222</li>
            <li>3333333333</li>
        </ul>
    </div>

这样就会有问题;

请问各位大佬,平时都是怎么写这个需求的啊…

阅读 14.1k
13 个回答

这个简单,你把下拉菜单和点击选项写在同一个父级元素中,给父级元素添加点击事件就好了

做一个透明遮罩,给这个遮罩添加点击事件

你把有问题的图或者BUG也列出来啊

点空白处元素不就失焦了么,那应该触发blur事件吧……

在document.click里 用jQuery.contains()来判断当前点击的dom是否在下拉框内

  1. 在下拉框点击事件的事件处理函数中 给body(这个body得要够大,太小的话直接绑到document上也还行吧)添加一个一次性的点击事件用来隐藏下拉框

伪代码
document.body.addEventListener("click",hideSelect,{once:true})

2.在下拉框点击事件处理函数(就在上面那坨代码下写就行) 和 下拉框弹出的内容上的点击事件处理函数 里面添加阻止冒泡
伪代码
e.stopPropagation

这应该算简单的了吧


  • 下拉框为什么不用select 这样你就不用纠结这个了
  • 可以在你这个下拉框和其他内容间来一个透明遮罩层 当开启下拉框时就让这个这遮罩层出现 在遮罩层绑定点击事件 点击它就关掉下拉框然后去掉该遮罩层

我还是觉得用select简单粗暴?

有两种方案可以解决:
1.在你的输入框下下拉框下面添加一个透明层,给这个透明层加点击事件就可以解决。
2.给dom添加点击事件,循环制跟节点,判断是不是你要的下拉框,如果不是就收起下拉框。

这两张方法,个人推荐第一种,理由就是不用判断很多dom。

事件冒泡不可以吗

之前用过的

// 点击列表以外任何地方,隐藏列表
    $(document).mouseup(function(e){
      var _con = $(shareMean);   // 目标区域
      if(!_con.is(e.target) && _con.has(e.target).length === 0){ 
        shareMean.hide();
      }
    });

参考下实现的代码~~~
在点击下拉以及选择item时阻止事件冒泡
然后为body添加一个click监听,当事件能冒泡到body时,关闭所有的pop下拉框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

        body{
            width: 100vw;
            height: 100vh;
            padding: 0;
            margin: 0;
        }
        .action-bar{
            position: absolute;
            left:0;
            top:0;
            width: 100%;
            height: 50px;
            background-color: lightgreen;

            display: flex;
            justify-content: flex-start;
            align-items: center;
        }

        .select-wrap{
            width: 100px;
            height: 100%;
            box-sizing: border-box;
            padding-top: 5px;
            padding-bottom: 5px;
            position: relative;
            padding-right: 10px;
            padding-left: 10px;

            position: relative;

        }

        .select-span{
            width: 100%;
            height: 100%;
            border-radius: 5px;
            border: 1px solid #cccccc;
            box-sizing: border-box;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }
        .select-list{
            display: none;

            position: absolute;
            left: 10px;
            top: 50px;
            width: 100px;
            list-style: none;
            padding: 5px;
            margin: 0;
            border: 1px solid red;

        }
        .select-wrap.active ul.select-list{
            display: block;
        }

        ul.select-list{
            list-style: none;
        }
        ul.select-list li{
            background-color: grey;
            background-color: grey;
            margin-bottom: 5px;
            overflow: hidden;
            cursor: pointer;
        }
    </style>
    
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script>
        $(function(){

            $(".select-wrap .select-span").on("click",function(event){
                $('body').find(".select-wrap").removeClass("active");
                $(this).parents(".select-wrap").toggleClass("active");
                event.stopPropagation();
                addCloseAllSelectPopListener();
            });

            $(".select-wrap ").on("click","ul.select-list li",function(event){
                console.log($(this).text()+" selected ");
                
                $('body').find(".select-wrap").removeClass("active");
                event.stopPropagation();
            });


            function addCloseAllSelectPopListener(){
                $('body').on("click",function closeEventListener(event){
                    $('body').find(".select-wrap").removeClass("active");
                    $(event.currentTarget).off("click",closeEventListener);
                });

            }
        });
    </script>
   
</head>
<body>
    <div class="action-bar">
        <div class="select-wrap">
            <div class="select-span">
                <span>选择一个</span>
            </div>
            <ul class="select-list">
                <li>1111111111</li>
                <li>2222222222</li>
                <li>3333333333</li>
            </ul>
        </div>

        <div class="select-wrap">
            <div class="select-span">
                <span>选择一个</span>
            </div>
            <ul class="select-list">
                <li>1111111111</li>
                <li>2222222222</li>
                <li>3333333333</li>
            </ul>
        </div>

    </div>


</body>
</html>

用jquery循环判断点击的是哪个,点击的这个出现,其他的收起,然后再用事件委派来点击空白处让其消失就可以了

项目里的写的 自己看代码 肯定能理解
clipboard.png
clipboard.png
clipboard.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题