下拉菜单仅在鼠标悬停和点击事件时闪烁。

huangapple go评论76阅读模式
英文:

Dropdown menu that opens with mouseover and click event only flickering

问题

以下是您要翻译的内容:

我正在尝试创建一个下拉菜单,点击按钮或悬停在按钮上时打开。

使用我现有的代码,下拉菜单在点击或悬停时会闪烁。换句话说,显示和不透明度不会保持。我希望能够点击或悬停在下拉菜单头部以显示下拉菜单。

HTML:

<div class="menu-link dropdown">
    <p class="dropdown-select">Item</p>
    <div class="dropdown-menu">
        <div class="top">
            <div class="arr-wrap">
                <div class="arr"></div>
            </div>
        </div>
        <p class="menu-link"><a href="./link.html">Item</a></p>
        <p class="menu-link"><a href="./link.html">Item</a></p>
        <p class="menu-link"><a href="./item.html">Item</a></p>
        <p class="menu-link"><a href="./item.html">Item</a></p>
        <p class="menu-link"><a href="./item.html">Item</a></p>
    </div>
</div>

CSS:

.menu-link {
    width: 100px;
    text-align: right;
    transition: 0.3s;
    margin-right: 25px;
}
.dropdown .menu-link {
    width: 200px;
    text-align: left;
    padding: 15px 0px;
    margin-left: 35px;
    height: 25px;
}
.dropdown-menu {
    position: absolute;
    top: 100px;
    opacity: 0;
    width: fit-content;
    height: fit-content;
    margin-left: -8px;
    width: fit-content;
    flex-flow: column;
    z-index: 3;
    border-radius: 10px;
    transition: 0.2s;
    background-color: white;
    box-shadow: 2px 2px 10px lightgrey;
    display: none;
}

.dropdown-select {
    height: fit-content;
}

.menu .menu-link {
    width: 100px;
    text-align: right;
    transition: 0.3s;
    margin-right: 25px;
}
.dropdown .menu-link {
    width: 200px;
    text-align: left;
    padding: 15px 0px;
    margin-left: 35px;
    height: 25px;
}
.dropdown-menu {
    position: absolute;
    top: 100px;
    opacity: 0;
    width: fit-content;
    height: fit-content;
    margin-left: -8px;
    width: fit-content;
    flex-flow: column;
    z-index: 3;
    border-radius: 10px;
    transition: 0.2s;
    background-color: white;
    box-shadow: 2px 2px 10px lightgrey;
    display: none;
}
.dropdown-select {
    height: fit-content;
}
.display {
    display: flex;
    opacity: 1;
    z-index: 3;
}

JavaScript:

document.addEventListener('DOMContentLoaded', load, false);

function load() {
    document.getElementsByClassName("dropdown")[0].addEventListener("click", dropdown, false);
    document.getElementsByClassName("dropdown")[0].addEventListener("mouseover", dropdown, false);
}

function dropdown() {
    var dropdown = document.getElementsByClassName("dropdown-menu")[0];

    dropdown.classList.toggle("display");
}
英文:

I am trying to create a dropdown menu that opens upon clicking a button, or hovering over it.

With the code I have, the dropdown menu flickers upon clicking or hovering. In other words, the display and opacity doesn't stay. I want to be able to either click or hover over the dropdown menu header to display the dropdown menu.

HTML:

&lt;div class=&quot;menu-link dropdown&quot;&gt;
&lt;p class=&quot;dropdown-select&quot;&gt;Item&lt;/p&gt;
&lt;div class=&quot;dropdown-menu&quot;&gt;
&lt;div class=&quot;top&quot;&gt;
&lt;div class=&quot;arr-wrap&quot;&gt;
&lt;div class=&quot;arr&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./link.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./link.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./item.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./item.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./item.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

CSS:

.menu-link {
width: 100px;
text-align: right;
transition: 0.3s;
margin-right: 25px;
}
.dropdown .menu-link {
width: 200px;
text-align: left;
padding: 15px 0px;
margin-left: 35px;
height: 25px;
}
.dropdown-menu {
position: absolute;
top: 100px;
opacity: 0;
width: fit-content;
height: fit-content;
margin-left: -8px;
width: fit-content;
flex-flow: column;
z-index: 3;
border-radius: 10px;
transition: 0.2s;
background-color: white;
box-shadow: 2px 2px 10px lightgrey;
display: none;
}
.dropdown-select {
height: fit-content;
}
.menu .menu-link {
width: 100px;
text-align: right;
transition: 0.3s;
margin-right: 25px;
}
.dropdown .menu-link {
width: 200px;
text-align: left;
padding: 15px 0px;
margin-left: 35px;
height: 25px;
}
.dropdown-menu {
position: absolute;
top: 100px;
opacity: 0;
width: fit-content;
height: fit-content;
margin-left: -8px;
width: fit-content;
flex-flow: column;
z-index: 3;
border-radius: 10px;
transition: 0.2s;
background-color: white;
box-shadow: 2px 2px 10px lightgrey;
display: none;
}
.dropdown-select {
height: fit-content;
}
.display {
display: flex;
opacity: 1;
z-index: 3;
}

JavaScript:

document.addEventListener(&#39;DOMContentLoaded&#39;, load, false);
function load() {
document.getElementsByClassName(&quot;dropdown&quot;)[0].addEventListener(&quot;click&quot;, dropdown, false);
document.getElementsByClassName(&quot;dropdown&quot;)[0].addEventListener(&quot;mouseover&quot;, dropdown, false);
}
function dropdown() {
var dropdown = document.getElementsByClassName(&quot;dropdown-menu&quot;)[0];
dropdown.classList.toggle(&quot;display&quot;);
}

答案1

得分: 1

这是一个容易犯的错误:
菜单闪烁是因为“mouseover”在鼠标稍微移动到元素上时就会触发,所以当你将鼠标移动到下拉菜单上时,mouseover会不断调用函数,从而切换“display”类,所以它会打开,然后关闭,然后再次打开,依此类推,无限循环。

要修复它,你可以尝试像这样做:

document.getElementsByClassName("dropdown")[0].addEventListener("click", dropdownClick, false);
document.getElementsByClassName("dropdown")[0].addEventListener("mouseenter", dropdownMouseEnter, false);
document.getElementsByClassName("dropdown")[0].addEventListener("mouseleave", dropdownMouseLeave, false);

function dropdownClick() {
    var dropdown = document.getElementsByClassName("dropdown-menu")[0];
    dropdown.classList.toggle("display");
}

function dropdownMouseEnter() {
    var dropdown = document.getElementsByClassName("dropdown-menu")[0];
    dropdown.classList.add("display");
}

function dropdownMouseLeave() {
    var dropdown = document.getElementsByClassName("dropdown-menu")[0];
    dropdown.classList.remove("display");
}

这不是制作下拉菜单的最佳方法,但这将使你原本想要的功能更好地工作。

如前所述,mouseover会在鼠标光标移动到元素上时触发,而mouseenter会在鼠标首次悬停在元素上时触发,mouseleave会在鼠标不再悬停在元素上时触发。

我稍微修改了一下,使它更加实用。查看下面的结果:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function _(id) { return document.getElementById(id); }

_("dropdown1").addEventListener("click", dropdownClick, false);
_("dropdown1").addEventListener("mouseenter", dropdownMouseEnter, false);
_("dropdown1").addEventListener("mouseleave", dropdownMouseLeave, false);

function dropdownClick() {
    _("dropdown1").classList.toggle("show");
}

function dropdownMouseEnter() {
    _("dropdown1").classList.add("show");
}

function dropdownMouseLeave() {
    _("dropdown1").classList.remove("show");
}

<!-- language: lang-css -->

*, *::before, *::after {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -ms-box-sizing: border-box;
    -o-box-sizing: border-box;
    box-sizing: border-box;
    font-family: 'Open Sans', sans-serif;
    font-weight: 500;
    margin: 0;
    padding: 0;
}

body {
    background-color: #eee;
    margin: 0.5rem;
}

.dropdown-wrap {
    position: absolute;
}

.dropdown-wrap .menu-link {
    padding: 1rem;
}

.dropdown-wrap .dropdown-select {
    padding: 1rem;
    cursor: pointer;
    width: 7rem;
    background-color: white;
    border-radius: 0.8rem;
}

.dropdown {
    min-width: 12rem;
    text-align: left;
    position: absolute;
    opacity: 0;
    display: flex;
    flex-flow: column;
    left: 0;
    top: calc(100% + 0.5rem);
    z-index: 3;
    border-radius: 0.8rem;
    transition: 0.2s;
    background-color: white;
    box-shadow: 2px 2px 10px lightgrey;
    transform-origin: top left;
    scale: 0;
}

.dropdown-wrap.show .dropdown {
    scale: 1;
    opacity: 1;
}

<!-- language: lang-html -->

<div id="dropdown1" class="dropdown-wrap">
    <p class="dropdown-select">Item</p>
    <div class="dropdown">
        <p class="menu-link"><a href="./link.html">Item</a></p>
        <p class="menu-link"><a href="./link.html">Item</a></p>
        <p class="menu-link"><a href="./item.html">Item</a></p>
        <p class="menu-link"><a href="./item.html">Item</a></p>
        <p class="menu-link"><a href="./item.html">Item</a></p>
    </div>
</div>

<!-- end snippet -->
英文:

It's an easy mistake:
The menu flickers because "mouseover" triggers every time the mouse moves over the element just by a tiny bit. so when you move the mouse over the dropdown menu, mouseover it's constantly calling the function which toggles the "display" class, so it opens, then it closes, then it opens again, and so on to infinity.

to fix it, you should try something like this:

document.getElementsByClassName(&quot;dropdown&quot;)[0].addEventListener(&quot;click&quot;, dropdownClick, false);
document.getElementsByClassName(&quot;dropdown&quot;)[0].addEventListener(&quot;mouseenter&quot;, dropdownMouseEnter, false);
document.getElementsByClassName(&quot;dropdown&quot;)[0].addEventListener(&quot;mouseleave&quot;, dropdownMouseLeave, false);
function dropdownClick() {
var dropdown = document.getElementsByClassName(&quot;dropdown-menu&quot;)[0];
dropdown.classList.toggle(&quot;display&quot;);
}
function dropdownMouseEnter() {
var dropdown = document.getElementsByClassName(&quot;dropdown-menu&quot;)[0];
dropdown.classList.add(&quot;display&quot;);
}
function dropdownMouseLeave() {
var dropdown = document.getElementsByClassName(&quot;dropdown-menu&quot;)[0];
dropdown.classList.remove(&quot;display&quot;);
}

This is not the best way to go on about making a dropdown menu, but this will make what you have work a lot better and more like you first intended.

As said before mouseover will trigger every time the mouse cursor moves over the element, while mouseenter will trigger once on mouse first hovering the element, and mouseleave will trigger it once more when the mouse is no longer hovering the element.

I've taken the liberty to rework it a bit to make it more functional. See below for the result:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function _(id) { return document.getElementById(id); }
_(&quot;dropdown1&quot;).addEventListener(&quot;click&quot;, dropdownClick, false);
_(&quot;dropdown1&quot;).addEventListener(&quot;mouseenter&quot;, dropdownMouseEnter, false);
_(&quot;dropdown1&quot;).addEventListener(&quot;mouseleave&quot;, dropdownMouseLeave, false);
function dropdownClick() {
_(&quot;dropdown1&quot;).classList.toggle(&quot;show&quot;);
}
function dropdownMouseEnter() {
_(&quot;dropdown1&quot;).classList.add(&quot;show&quot;);
}
function dropdownMouseLeave() {
_(&quot;dropdown1&quot;).classList.remove(&quot;show&quot;);
}

<!-- language: lang-css -->

*, *::before, *::after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
font-family: &#39;Open Sans&#39;, sans-serif;
font-weight: 500;
margin: 0;
padding: 0;
}
body {
background-color: #eee;
margin: 0.5rem;
}
.dropdown-wrap {
position: absolute;
}
.dropdown-wrap .menu-link {
padding: 1rem;
}
.dropdown-wrap .dropdown-select {
padding: 1rem;
cursor: pointer;
width: 7rem;
background-color: white;
border-radius: 0.8rem;
}
.dropdown {
min-width: 12rem;
text-align: left;
position: absolute;
opacity: 0;
display: flex;
flex-flow: column;
left: 0;
top: calc(100% + 0.5rem);
z-index: 3;
border-radius: 0.8rem;
transition: 0.2s;
background-color: white;
box-shadow: 2px 2px 10px lightgrey;
transform-origin: top left;
scale: 0;
}
.dropdown-wrap.show .dropdown {
scale: 1;
opacity: 1;
}

<!-- language: lang-html -->

&lt;div id=&quot;dropdown1&quot; class=&quot;dropdown-wrap&quot;&gt;
&lt;p class=&quot;dropdown-select&quot;&gt;Item&lt;/p&gt;
&lt;div class=&quot;dropdown&quot;&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./link.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./link.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./item.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./item.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;menu-link&quot;&gt;&lt;a href=&quot;./item.html&quot;&gt;Item&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月22日 03:24:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526525.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定