BS 5.0.2 - 防止下拉菜单的默认行为 - 在 BS4 中有效,但在 BS5 中无效

问题描述

在 BS4 中,我能够执行类似于以下操作(尽管在 jquery 中)以防止基于满足条件的下拉列表。在 5.0.2 中,这似乎没有任何作用,下拉菜单仍然正常显示/隐藏。它现在不尊重 stopPropagation() 和 preventDefault() 还是现在需要以不同的方式处理?

document.querySelectorAll('.dropdown [data-bs-toggle="dropdown"]').forEach(function(dd) {
    dd.addEventListener('click',function(e) {

        if( *some condition met* ) {
            e.stopPropagation();
            e.preventDefault();
        }       
    });
});

在有人问之前......是的,我的条件得到了满足,这不是这里的问题。

解决方法

根据 OP 的 jsfiddle 示例修改答案

BS4 版本响应点击的 preventDefault() 并没有阻止 Bootstrap 的下拉,而是阻止了 Dallaslu’s multi-level dropdown –(Dallaslu 的代码触发了下拉切换)。

Dallaslu 确实有一个 Bootstrap 5 multi-level dropdown,在更新代码以使用 data-bs-dropend 而不是 dropright 后,它可以与 jsFiddle 中的菜单配合使用。

(function($bs) {
    const CLASS_NAME = 'has-child-dropdown-show';
    $bs.Dropdown.prototype.toggle = function(_orginal) {
        return function() {
            document.querySelectorAll('.' + CLASS_NAME).forEach(function(e) {
                e.classList.remove(CLASS_NAME);
            });
            let dd = this._element.closest('.dropdown').parentNode.closest('.dropdown');
            for (; dd && dd !== document; dd = dd.parentNode.closest('.dropdown')) {
                dd.classList.add(CLASS_NAME);
            }
            return _orginal.call(this);
        }
    }($bs.Dropdown.prototype.toggle);

    document.querySelectorAll('.dropdown').forEach(function(dd) {
        dd.addEventListener('hide.bs.dropdown',function(e) {
            if (this.classList.contains(CLASS_NAME)) {
                this.classList.remove(CLASS_NAME);
                e.preventDefault();
            }
            if (e.clickEvent && e.clickEvent.composedPath().some(el => el.classList && el.classList.contains('dropdown-toggle'))) {
                e.preventDefault();
            }
            e.stopPropagation(); // do not need pop in multi level mode
        });
    });

    // for hover
    function getDropdown(element) {
        return $bs.Dropdown.getInstance(element) || new $bs.Dropdown(element);
    }

    document.querySelectorAll('.dropdown-hover,.dropdown-hover-all .dropdown').forEach(function(dd) {
        dd.addEventListener('mouseenter',function(e) {
            let toggle = e.target.querySelector(':scope>[data-bs-toggle="dropdown"]');
            if (!toggle.classList.contains('show')) {
                getDropdown(toggle).toggle();
            }
        });
        dd.addEventListener('mouseleave',function(e) {
            let toggle = e.target.querySelector(':scope>[data-bs-toggle="dropdown"]');
            if (toggle.classList.contains('show')) {
                getDropdown(toggle).toggle();
            }
        });
    });
})(bootstrap);
/* ============  MOBILE VERSION OF THE HEADER NAV  ============ */

/* ============  HEADER AND LOGO  ============ */
#header {
    background-color: #000;
    font-weight: 400;
    padding: 0 1rem;
    font-size: 1rem;
}

/*logo*/
#header .navbar-brand {
    margin: auto;
    padding: .5625rem 1.625rem .5625rem 0;
    /*this centers the logo correctly as it is the width of the toggler*/
}

/*bottom spacing for entire dropdown menu*/
#header .navbar-nav {
    margin-bottom: 1rem;
}

/* ============  SPECIAL MENU STUFF  ============ */
/*navbar check for jquery*/
#navbar-check {
    display: none;
}

/*smart header hide/show*/
.navbar-showhide {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1030;
}

.navbar-showhide.scrolled-down {
    transform: translateY(-100%);
    transition: all 0.2s ease-in-out;
    visibility: hidden;
}

.navbar-showhide.scrolled-up {
    transform: translateY(0);
    transition: all 0.2s ease-in-out;
}

#header .dropdown-menu.megaFull,#header .dropdown-menu.megaLg {
    padding: .5rem 2rem 0;
}

#header .dropdown-menu.megaSub {
    padding: .5rem 3rem 0;
}

#header .dropdown-title {
    font-weight: 600;
    color: white;
    font-size: .9375rem;
    margin: 0 0 .5rem;
}

/* ============  MENU  ============ */
/*top links container*/
#header .nav-item {
    border-radius: .3rem;
}

/*top links*/
#header .nav-link,#header .nav-link:focus {
    padding: .5rem 1rem;
    color: gray;
}

#header .nav-link:hover {
    color: #fff;
}

/*top dropdown link solid color when open*/
#header .dropdown .dropdown-toggle[aria-expanded=true] {
    color: #fff;
}

/*dropdown arrows - remove bootstrap default*/
#header .dropdown .dropdown-toggle:after {
    border: 0;
    vertical-align: 0;
    margin: 0;
}

/*add custom dropdown arrows*/
#header .dropdown .dropdown-toggle[aria-expanded=false]:after {
    font-family: 'Font Awesome 5 Free';
    content: '\f107';
    /*fal fa-angle-down*/
    font-weight: 600;
    margin-left: .5rem;
    display: inline-block;
}

#header .dropdown .dropdown-toggle[aria-expanded=true]:after {
    font-family: 'Font Awesome 5 Free';
    content: '\f106';
    /*fal fa-angle-up*/
    font-weight: 600;
    margin-left: .5rem;
    display: inline-block;
}

/*dropdown box*/
#header .dropdown-menu {
    margin: 0;
    padding: 0;
    background-color: transparent;
    border-color: transparent;
}

/*dropdown box links inside*/
#header .dropdown-item {
    font-weight: 300;
    font-size: .9375rem;
    color: #ccc;
    padding: .25rem 2rem;
}

#header .dropdown-item:active,#header .dropdown-item:focus,#header .dropdown-item:hover,#header .dropdown .dropdown .dropdown-toggle[aria-expanded=true] {
    /*this keeps the open dropdown link solid*/
    background-color: transparent;
}

#header .dropdown-item:hover {
    color: #fff;
}

/*two levels*/
#header .dropdown-menu .dropdown-menu .dropdown-item {
    padding: .25rem 3rem;
}

/*three levels*/
#header .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item {
    padding: .25rem 4rem;
}

/*right side nav buttons*/
#header .ml-lg-auto .nav-item+.nav-item {
    margin-top: .25rem;
}

#header .ml-lg-auto .nav-link,#header .ml-lg-auto .nav-link:active,#header .ml-lg-auto .nav-link:focus,#header .ml-lg-auto .nav-link:hover {
    color: #fff !important;
    font-weight: 600;
}

/*blue dropdown*/
#header .dropBlue {
    background-color: #347fc0;
}

/*green dropdown*/
#header .dropGreen {
    background-color: #4fab4f;
}

/*form stuff*/
#header .dropForm .dropdown-menu {
    padding: 0 1.5rem 1rem;
    color: #fff;
}

#header .dropForm .dropdown-title {
    font-weight: 600;
    color: #fff;
    margin: 1rem 0 1rem;
}

/*remember me*/
#header .custom-control-label {
    font-size: .9375rem;
}

#header .custom-checkbox .custom-control-label::before {
    border: 0;
}

/*in misc so it works on all pages*/

.custom-control-label::after {
    top: .2rem;
}

#header .custom-control-input:focus~.custom-control-label::before {
    box-shadow: none;
}

#header .custom-control-label::before {
    background-color: #fff;
}

#header .custom-checkbox .custom-control-input:checked~.custom-control-label::before {
    background-color: darken(#347fc0,10%);
}

/*the toggler*/
#header .navbar-toggler {
    font-size: 1.750rem;
    /*makes a 26px (with padding) wide fontawesome icon*/
}

#header .navbar-toggler,#header .navbar-toggler.collapsed:hover {
    color: #4fab4f;
}

/*when menu is closed and not hovered*/
#header .navbar-toggler.collapsed {
    color: #fff;
}


/* ============  DESKTOP VERSION OF THE HEADER NAV  ============ */

@media only screen and (min-width: 992px) {

    /* ============  HEADER AND LOGO  ============ */
    /*bottom spacing for entire dropdown menu*/
    #header .navbar-nav {
        margin-bottom: 0;
    }

    /* ============  SPECIAL MENU STUFF  ============ */
    /*navbar check for jquery*/
    #navbar-check {
        display: block;
    }

    /*smart header hide/show*/
    .navbar-showhide.scrolled-down .dropdown-menu {
        opacity: 0 !important;
        visibility: hidden;
        transition: all 0.2s ease-in-out;
    }

    #header .hasmegaFull {
        position: static !important;
    }

    #header .megaFull {
        left: 0;
        right: 0;
        width: 100%;
    }

    #header .megaSub {
        left: 100%;
        top: 0;
        min-height: 100%;
    }

    #header .dropdown-menu.megaFull,#header .dropdown-menu.megaSub,#header .dropdown-menu.megaLg {
        padding: 1rem;
        color: #bfe1ff;
    }

    #header .dropdown-title {
        font-weight: 600;
        color: #fff;
    }

    /* ============  MENU  ============ */
    /*top links container*/
    #header .nav-item {
        border-radius: 0;
    }

    /*top links*/
    #header .nav-link,#header .nav-link:focus {
        padding: 1.125rem 1rem;
        color: #ccc;

        /*top link and dropdown menu transition should match*/
        /*transition: all .15s ease-in-out;*/
    }

    #header .nav-link:hover {
        color: #fff;
        background-color: #4fab4f;
    }

    /*top link colors*/
    #header .dropBlue .nav-link,#header .dropBlue .dropdown .dropdown-toggle[aria-expanded="true"],#header .dropBlue .dropdown-menu {
        background-color: #347fc0 !important;
        border-color: #347fc0;
    }

    #header .dropGreen .nav-link,#header .dropGreen .dropdown .dropdown-toggle[aria-expanded="true"],#header .dropGreen .dropdown-menu {
        background-color: #4fab4f !important;
        border-color: #4fab4f;
    }

    /*top dropdown link solid color when open*/
    #header .dropdown .dropdown-toggle[aria-expanded=true] {
        color: #fff;
        background-color: #4fab4f;
    }

    /*top links remove dropdown arrow*/
    #header .dropdown .dropdown-toggle[aria-expanded="false"]:after,#header .dropdown .dropdown-toggle[aria-expanded="true"]:after {
        content: '';
        font-family: inherit;
        margin: 0;
    }

    /*add custom dropdown arrows for submenus*/
    #header .dropdown .dropdown .dropdown-toggle[aria-expanded="false"]:after {
        font-family: 'Font Awesome 5 Free';
        content: '\f105';
        /*fal fa-angle-right*/
        font-weight: 600;
        margin-left: .5rem;
        display: inline-block;
        float: right;
    }

    #header .dropdown .dropdown .dropdown-toggle[aria-expanded="true"]:after {
        font-family: 'Font Awesome 5 Free';
        content: '\f104';
        /*fal fa-angle-left*/
        font-weight: 600;
        margin-left: .5rem;
        display: inline-block;
        float: right;
    }

    /*dropdown*/
    #header .dropdown-menu {
        background-color: #4fab4f;
        border-radius: .5rem;
        border-top-left-radius: 0;
        border-top-right-radius: 0;
        padding: .5rem .35rem;
        /*hover doesn't like this*/
        /*padding: .5rem 0;*/
        border-color: #4fab4f;
        border-top: 0;

        /*top link and dropdown menu transition should match*/
        /*  display: block;
            opacity: 0;
            pointer-events: none;
            transition: all .15s ease-in-out;
        */
    }

    #header .show>.dropdown-menu {
        pointer-events: auto;
        opacity: 1;
    }

    #header .dropdown-menu li {
        position: relative;
    }

    #header .dropdown-menu li.hasmegaSub {
        position: relative;
    }

    /*dropdown box links inside regular*/
    #header .dropdown-item {
        color: #fff;
        padding: .3125rem .65rem;
        /*hover doesn't like this*/
        /*padding:.3125rem 1rem;*/
        border-radius: 0.5rem;
        /*hover doesn't like this*/
        /*border-radius: 0;*/
    }

    #header .dropdown-item:active,/*#header .dropdown-item:focus,*/
    /*when on it leaves submenu link highlighted even when its submenu is closed*/
    #header .dropdown-item:hover,#header .dropdown .dropdown .dropdown-toggle[aria-expanded="true"] {
        color: #fff;
        background-color: lighten(#4fab4f,7%);
    }

    /*multi level*/
    #header .dropdown-menu .dropdown-menu {
        border-radius: .5rem;
        border: 1px solid darken(#4fab4f,5%);
        top: calc(-.5rem - 1px);
        /*use calc when using border on these boxes - 1px covers border and .5rem is the top padding of the box*/
        /*left: calc(100% - .25rem);*/
        /*use to shift box a little to the left to overlap the previous*/
    }

    #header .dropdown-menu .dropdown-menu .dropdown-item,#header .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item {
        padding: .3125rem .65rem;
        /*hover doesn't like this*/
        /*padding:.3125rem 1rem;*/
    }

    /*right side nav buttons*/
    #header .ml-lg-auto .nav-item+.nav-item {
        margin-top: 0;
    }

    /*form stuff*/
    #header .dropForm .dropdown-menu {
        padding: 0 1rem 1rem;
        min-width: 17.875rem;
    }
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>

<div id="wrapper">

    <!-- BEGIN NAVBAR -->
    <nav id="header" class="navbar navbar-expand-lg navbar-showhide dropdown-hover-all">
        <div class="container" style="position: relative;">
            <button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
                <i class="fas fa-bars"></i>
            </button>
            <a class="navbar-brand" href="/">
                <img alt="test" src="https://via.placeholder.com/80x42.png" height="42">
            </a>
            <div id="navbar" class="navbar-nav-scroll collapse navbar-collapse">

                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a class="nav-link" href="/test/">Regular Link</a>
                    </li>
                    <li class="nav-item dropdown">
                        <a id="dropdown01" class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">test no link</a>
                        <ul class="dropdown-menu" aria-labelledby="dropdown01">
                            <li><a class="dropdown-item" href="/test/">one</a></li>
                            <li class="dropdown dropend">
                                <a id="dropdown02" class="dropdown-item dropdown-toggle" href="/test/" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">test with link</a>
                                <ul class="dropdown-menu" aria-labelledby="dropdown02">
                                    <li><a class="dropdown-item" href="/test/">one</a></li>
                                    <li class="dropdown dropend">
                                        <a id="dropdown03" class="dropdown-item dropdown-toggle" href="/test/" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">test with link</a>
                                        <ul class="dropdown-menu" aria-labelledby="dropdown03">
                                            <li><a class="dropdown-item" href="/test/">one</a></li>
                                            <li><a class="dropdown-item" href="/test/">two</a></li>
                                            <li><a class="dropdown-item" href="/test/">three</a></li>
                                        </ul>
                                    </li>
                                    <li><a class="dropdown-item" href="/test/">three</a></li>
                                </ul>
                            </li>
                            <li><a class="dropdown-item" href="/test/">two</a></li>
                        </ul>
                    </li>

                    <li class="nav-item dropdown">
                        <a id="DD_megaSub" class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">megaSub no link</a>
                        <ul class="dropdown-menu" aria-labelledby="DD_megaSub">
                            <li><a class="dropdown-item" href="/test/">test</a></li>
                            <li class="dropdown dropend hasmegaSub">
                                <a id="DD_Mega4" class="dropdown-item dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">test no link</a>
                                <div class="dropdown-menu megaSub" style="min-width:400px;" aria-labelledby="DD_Mega4">
                                    <div class="row row-cols-1 row-cols-sm-2">
                                        <div class="col pb-3 pb-sm-1 pb-lg-0">
                                            <h6 class="dropdown-title">Title Menu One</h6>
                                            <ul class="list-unstyled">
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                            </ul>
                                        </div>
                                        <div class="col pb-1 pb-lg-0">
                                            <h6 class="dropdown-title">Title Menu Two</h6>
                                            <ul class="list-unstyled">
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                            </ul>
                                        </div>
                                    </div>
                                </div>
                            </li>
                            <li class="dropdown">
                                <a id="DD_Mega5" class="dropdown-item dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">test no link</a>
                                <div class="dropdown-menu megaSub" style="min-width:400px;" aria-labelledby="DD_Mega5">
                                    <div class="row row-cols-1 row-cols-sm-2">
                                        <div class="col pb-3 pb-sm-1 pb-lg-0">
                                            <h6 class="dropdown-title">Title Menu One</h6>
                                            <ul class="list-unstyled">
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                            </ul>
                                        </div>
                                        <div class="col pb-1 pb-lg-0">
                                            <h6 class="dropdown-title">Title Menu Two</h6>
                                            <ul class="list-unstyled">
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                                <li><a href="/test/">Submenu item</a></li>
                                            </ul>
                                        </div>
                                    </div>
                                </div>
                            </li>
                        </ul>
                    </li>

                </ul>

                <ul class="navbar-nav ml-lg-auto">
                    <li class="nav-item dropGreen"><a class="nav-link" href="/test/"><i class="fas fa-arrow-circle-right fa-pr"></i>regular link</a></li>
                    <li class="nav-item dropdown dropForm dropBlue">
                        <a id="DD_Login" class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fas fa-user-circle fa-pr"></i>form no link</a>
                        <div class="dropdown-menu dropdown-menu-right" aria-labelledby="DD_Login">
                            <form class="" role="form" method="post" action="http://example.com" target="_blank" autocomplete="off">
                                <h6 class="dropdown-title">Sign in to your account :</h6>
                                <div class="form-group">
                                    <label class="sr-only" for="signinUsername">Username</label>
                                    <div class="input-group">
                                        <div class="input-group-prepend">
                                            <span class="input-group-text"><i class="fas fa-user fa-fw"></i></span>
                                        </div>
                                        <input id="signinUsername" type="text" class="form-control" name="username" placeholder="username" />
                                    </div>
                                </div>
                                <div class="form-group">
                                    <label class="sr-only" for="signinPassword">Password</label>
                                    <div class="input-group">
                                        <div class="input-group-prepend">
                                            <span class="input-group-text"><i class="fas fa-lock-alt fa-fw"></i></span>
                                        </div>
                                        <input id="signinPassword" type="password" class="form-control" name="password" placeholder="password" />
                                    </div>
                                </div>
                                <div class="custom-control custom-checkbox">
                                    <input id="rememberMe" type="checkbox" class="custom-control-input" value="1" name="remember">
                                    <label for="rememberMe" class="custom-control-label">Remember me?</label>
                                </div>
                                <div class="form-group mt-3 mb-0">
                                    <input type="hidden" name="signin" value="signin">
                                    <button type="submit" class="btn btn-success btn-block">Login Now</button>
                                </div>
                            </form>
                        </div>
                    </li>
                </ul>

            </div>
        </div>
    </nav>
    <!-- END NAVBAR -->

</div>
<!-- END WRAPPER -->

<div id="navbar-check"></div>

我没有从您的 BS4 版本中添加用于处理触摸屏的代码,但该代码段确实显示了使用悬停的菜单。

我确实删除了一些菜单项,以便代码片段符合 Stackoverflow 的大小限制,但您仍然应该能够看到效果。