使用原版 javascript 在将鼠标悬停在父元素上后向其他元素添加/删除类



我已经浏览了许多类似的问题,但找不到一个具体的例子,可以在原版JS中回答如何在悬停的元素中添加和删除类到不同的元素。我知道这与设置循环和迭代元素有关,但我迷失在确切的过程中。

基本上,我的卡片上有一个关闭按钮,我希望关闭按钮仅在有人将鼠标悬停在卡片上时才显示。我添加了 2 个不同的类来显示和隐藏它,但是,我的脚本不起作用。

不幸的是,我不被允许使用JQuery。

var closeButton = document.getElementsByClassName('close');
var card = document.getElementsByClassName('.card')
for (var i = 0; i < card.length; i++) {
card[i].addEventListener("mouseover", function() {
for (var i = 0; i < closeButton.length; i++) {
closeButton[i].classList.add('shown');
closeButton[i].classList.remove('hidden');
}
});
card[i].addEventListener("mouseout", function() {
for (var i = 0; i < closeButton.length; i++) {
closeButton[i].remove('shown');
closeButton[i].add('hidden');
}
});
}
/*! normalize.css v1.1.0 | MIT License | git.io/normalize */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block
}
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1
}
audio:not([controls]) {
display: none;
height: 0
}
[hidden] {
display: none
}
html {
font-size: 100%;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%
}
html,
button,
input,
select,
textarea {
font-family: sans-serif
}
body {
margin: 0
}
a:active,
a:hover {
outline: 0
}
h1 {
font-size: 2em;
margin: .67em 0
}
h2 {
font-size: 1.5em;
margin: .83em 0
}
h3 {
font-size: 1.17em;
margin: 1em 0
}
h4 {
font-size: 1em;
margin: 1.33em 0
}
h5 {
font-size: .83em;
margin: 1.67em 0
}
h6 {
font-size: .67em;
margin: 2.33em 0
}
abbr[title] {
border-bottom: 1px dotted
}
b,
strong {
font-weight: bold
}
blockquote {
margin: 1em 40px
}
dfn {
font-style: italic
}
hr {
-webkit-box-sizing: content-box;
box-sizing: content-box;
height: 0
}
mark {
background: #ff0;
color: #000
}
p,
pre {
margin: 1em 0
}
code,
kbd,
pre,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em
}
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word
}
q {
quotes: none
}
q:before,
q:after {
content: '';
content: none
}
small {
font-size: 80%
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline
}
sup {
top: -0.5em
}
sub {
bottom: -0.25em
}
dl,
menu,
ol,
ul {
margin: 1em 0
}
dd {
margin: 0 0 0 40px
}
menu,
ol,
ul {
padding: 0 0 0 40px
}
nav ul,
nav ol {
list-style: none;
list-style-image: none;
padding: 0;
margin: 0
}
img {
border: 0;
-ms-interpolation-mode: bicubic
}
svg:not(:root) {
overflow: hidden
}
figure {
margin: 0
}
form {
margin: 0
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: .35em .625em .75em
}
legend {
border: 0;
padding: 0;
white-space: normal;
*margin-left: -7px
}
button,
input,
select,
textarea {
font-size: 100%;
margin: 0;
vertical-align: baseline;
*vertical-align: middle
}
button,
input {
line-height: normal
}
button,
select {
text-transform: none
}
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button;
cursor: pointer;
*overflow: visible
}
button[disabled],
html input[disabled] {
cursor: default
}
input[type="checkbox"],
input[type="radio"] {
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
*height: 13px;
*width: 13px
}
input[type="search"] {
-webkit-appearance: textfield;
-webkit-box-sizing: content-box;
box-sizing: content-box
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none
}
a:link {
text-decoration: none !important;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0
}
textarea {
overflow: auto;
vertical-align: top
}
table {
border-collapse: collapse;
border-spacing: 0
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: all 1s ease;
transition: all 1s ease;
}
html {
font-size: 100%;
font-family: sans-serif;
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
background: #f8f8f8;
}
#wrapper {
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0 auto;
padding: 20px;
max-width: 980px;
background: #fff;
-webkit-box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
border-radius: 2px;
}
.clearfix {
overflow: auto;
}
.clearfix::after {
content: "";
clear: both;
display: table;
}
.headline {
padding: 0 10px;
}
.headline .promoted-stories {
font-weight: bold;
color: #404040;
}
.headline .taboola-link {
float: right;
}
.headline .taboola-link a {
font-weight: 300;
line-height: normal;
text-align: right;
color: #888888;
font-size: 11px;
}
.cards {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.card {
display: block;
min-height: 1px;
margin: 1%;
-webkit-box-flex: 0;
-ms-flex: 0 0 31.33333333%;
flex: 0 0 31.33333333%;
-webkit-box-shadow: 0px 0px 1px -2px rgba(0, 0, 0, 0.2), 0px 0px 2px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 1px -2px rgba(0, 0, 0, 0.2), 0px 0px 2px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12);
-webkit-transition: all .25s;
transition: all .25s;
position: relative;
}
.card:hover {
-webkit-transform: translate(0, -2px);
transform: translate(0, -2px);
-webkit-box-shadow: 0px 1px 2px -1px rgba(0, 0, 0, 0.2), 0px 3px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 1px 2px -1px rgba(0, 0, 0, 0.2), 0px 3px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
}
.overlay {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
.card .thumbnail {
display: block;
height: 130px;
}
.card img {
height: 100%;
width: 100%;
border: none;
-o-object-fit: cover;
object-fit: cover;
-o-object-position: 50% 50%;
object-position: 50% 50%;
}
.card-content {
padding: 5px 10px 25px;
}
.card .card-content .card-title {
margin: 5px 0 0 0;
overflow: hidden;
color: #000;
font-weight: bold;
max-height: 72px;
font-size: .875rem;
line-height: 1.5rem;
text-decoration: none;
}
.card .card-content .category {
color: #999999;
font-size: 11.0px;
font-weight: bold;
text-decoration: none;
margin: 5px 0 0 0;
overflow: hidden;
max-height: 52px;
}
.close {
position: absolute;
right: 15px;
top: 5px;
}
.shown {
display: block;
}
.hidden {
display: none;
}
.close:before,
.close:after {
position: absolute;
left: 0;
right: 0;
content: ' ';
height: 15px;
width: 2px;
background-color: #fff;
}
.close:before {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.close:after {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
@media only screen and (max-width: 768px) {
.card {
-webkit-box-flex: 0;
-ms-flex: 0 0 48%;
flex: 0 0 48%;
}
}
@media only screen and (max-width: 480px) {
.card {
-webkit-box-flex: 0;
-ms-flex: 0 0 98%;
flex: 0 0 98%;
margin: 2%;
}
.card .thumbnail,
.card .thumbnail a:first-of-type {
height: 170px;
}
}
<section id="wrapper">
<div class="headline clearfix">
<span class="promoted-stories">Promoted stories</span>
<span class="taboola-link"><a href="#">Sponsored Links by Taboola</a></span>
</div>
<div class="cards clearfix">
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="3 Reasons Why You Haven't Found Your Match Yet">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">3 Reasons Why You Haven't Found Your Match Yet</h2>
<p class="category">Dating life</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Harry And Meghan Announce Baby On The Way">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Harry And Meghan Announce Baby On The Way</h2>
<p class="category">Royals</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Things Get Seriously Real As RuPaul Cast Open Up">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Things Get Seriously Real As RuPaul Cast Open Up</h2>
<p class="category">Celebrities</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="A Tiger Collapsed In A Russian Circus Mid-Show">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">A Tiger Collapsed In A Russian Circus Mid-Show</h2>
<p class="category">Circus</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Engagement On The Cards For Jack And Dani">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Engagement On The Cards For Jack And Dani</h2>
<p class="category">Dating life</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Attwood Hits Back At Rumours Of Dani Dyer Fued">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Attwood Hits Back At Rumours Of Dani Dyer Fued</h2>
<p class="category">Gossip</p>
</div><!-- .card-content -->
</article><!-- .card -->
</div>
</section>

在你的代码中,document.getElementsByClassName('.card')会寻找 类名为.card而不是card的元素。此外,此功能不需要两个类。只需删除hidden类即可完成工作。

这是更新的JS代码:

(function() {
document.querySelectorAll(".card").forEach(function(card) {
card.addEventListener("mouseenter", function() {
card.querySelector(".close").classList.remove("hidden");
})
card.addEventListener("mouseout", function() {
card.querySelector(".close").classList.add("hidden");
})
})
})()

试试吧

function find( el, tagName ) {
tagName = tagName.toUpperCase();
let nsi = el.nextElementSibling;
if ( nsi === null || nsi.children === null || nsi.children.length === 0 ) return null;
for ( let c of nsi.children ) {
if ( c.tagName === tagName ) return c;
}
return null;
};
let card = document.getElementsByClassName( 'card' );
for ( let c of card ) {
c.addEventListener( "mouseover", function ( e ) {
let el = find( e.target, "a" );
if ( el === null ) return;
el.classList.add( 'shown' );
el.classList.remove( 'hidden' );
}, false );
c.addEventListener( "mouseout", function ( e ) {
let open = document.querySelectorAll( ".close.shown" );
if ( open !== null ) {
for ( let obtn of open ) {
obtn.classList.remove( 'shown' );
obtn.classList.add( 'hidden' );
}
}
}, false );
};

运行 jsfiddle

你的错误 JavaScript:
i)closeButton[i].remove( 'shown' );将是运行时错误;这里没有typeof("function")删除,你必须从 classList 中删除类 ii)closeButton[i].add( 'hidden' );将是运行时错误;这里没有添加typeof("function"),你必须将类添加到 classList

中 iii)var card = document.getElementsByClassName('.card')card长度应该是 0,因为它会找到所有.card而不是card

编辑

//Correction
//closeButton[i].classList.remove( 'shown' ); 
//closeButton[i].classList.add( 'hidden' ); 
//var card = document.getElementsByClassName('card');

了解更多 让 迭代数组

你实际的 JavaScript 问题是你有嵌套循环,这些循环声明并使用与父循环相同的变量,这会重置外部循环计数器,因此你不会按照你需要的方式循环。对内部循环使用不同的变量将是那里的关键。

此外,当您在嵌套循环中访问在更高范围内声明的同一变量时,它会在i变量周围设置一个"闭包"。这会导致所有卡片共享相同的i值,并且当用户将鼠标悬停在任何卡片上时,i比卡片数组的length多一个,因此超出了查找任何要匹配的卡片的范围。解决方案是简单地用let声明i,而不是var,从而设置块级范围并避免闭包。


现在,话虽如此,没有必要有一个显示类和一个隐藏类。您只需要一个隐藏类,您只需应用或删除该类即可控制按钮的可见性。


但是,实际上,你根本不需要任何JavaScript,只需要一个小CSS,它根据祖先"卡片"是否悬停来控制"按钮"的display

/* Default styling of "close" buttons is hidden */
.card a.close {
display:none;
}
/* When ancestor "card" is hovered, change display to shown */
.card:hover a.close{
display:block;
font-weight:bold;
}
/* ******************************** */
/*! normalize.css v1.1.0 | MIT License | git.io/normalize */
figure {
margin: 0
}
a:link {
text-decoration: none !important;
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: all 1s ease;
transition: all 1s ease;
}
html {
font-size: 100%;
font-family: sans-serif;
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
background: #f8f8f8;
}
#wrapper {
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0 auto;
padding: 20px;
max-width: 980px;
background: #fff;
-webkit-box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
border-radius: 2px;
}
.clearfix {
overflow: auto;
}
.clearfix::after {
content: "";
clear: both;
display: table;
}
.headline {
padding: 0 10px;
}
.headline .promoted-stories {
font-weight: bold;
color: #404040;
}
.headline .taboola-link {
float: right;
}
.headline .taboola-link a {
font-weight: 300;
line-height: normal;
text-align: right;
color: #888888;
font-size: 11px;
}
.cards {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.card {
display: block;
min-height: 1px;
margin: 1%;
-webkit-box-flex: 0;
-ms-flex: 0 0 31.33333333%;
flex: 0 0 31.33333333%;
-webkit-box-shadow: 0px 0px 1px -2px rgba(0, 0, 0, 0.2), 0px 0px 2px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 1px -2px rgba(0, 0, 0, 0.2), 0px 0px 2px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12);
-webkit-transition: all .25s;
transition: all .25s;
position: relative;
}
.card:hover {
-webkit-transform: translate(0, -2px);
transform: translate(0, -2px);
-webkit-box-shadow: 0px 1px 2px -1px rgba(0, 0, 0, 0.2), 0px 3px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 1px 2px -1px rgba(0, 0, 0, 0.2), 0px 3px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
}
.overlay {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
.card .thumbnail {
display: block;
height: 130px;
}
.card img {
height: 100%;
width: 100%;
border: none;
-o-object-fit: cover;
object-fit: cover;
-o-object-position: 50% 50%;
object-position: 50% 50%;
}
.card-content {
padding: 5px 10px 25px;
}
.card .card-content .card-title {
margin: 5px 0 0 0;
overflow: hidden;
color: #000;
font-weight: bold;
max-height: 72px;
font-size: .875rem;
line-height: 1.5rem;
text-decoration: none;
}
.card .card-content .category {
color: #999999;
font-size: 11.0px;
font-weight: bold;
text-decoration: none;
margin: 5px 0 0 0;
overflow: hidden;
max-height: 52px;
}
.close {
position: absolute;
right: 15px;
top: 5px;
}
.close:before,
.close:after {
position: absolute;
left: 0;
right: 0;
content: ' ';
height: 15px;
width: 2px;
background-color: #fff;
}
.close:before {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.close:after {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
<section id="wrapper">
<div class="headline clearfix">
<span class="promoted-stories">Promoted stories</span>
<span class="taboola-link"><a href="#">Sponsored Links by Taboola</a></span>
</div>
<div class="cards clearfix">
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="3 Reasons Why You Haven't Found Your Match Yet">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">3 Reasons Why You Haven't Found Your Match Yet</h2>
<p class="category">Dating life</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Harry And Meghan Announce Baby On The Way">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Harry And Meghan Announce Baby On The Way</h2>
<p class="category">Royals</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Things Get Seriously Real As RuPaul Cast Open Up">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Things Get Seriously Real As RuPaul Cast Open Up</h2>
<p class="category">Celebrities</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="A Tiger Collapsed In A Russian Circus Mid-Show">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">A Tiger Collapsed In A Russian Circus Mid-Show</h2>
<p class="category">Circus</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Engagement On The Cards For Jack And Dani">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Engagement On The Cards For Jack And Dani</h2>
<p class="category">Dating life</p>
</div><!-- .card-content -->
</article><!-- .card -->
<article class="card">
<a class="overlay" href="#overlay-link"></a>
<figure class="thumbnail">
<img src="https://img.ohmymag.co.uk/headline/480/0f2af4ec6e8d3971480358d00e67e2e8117d994e.jpg" alt="Attwood Hits Back At Rumours Of Dani Dyer Fued">
<a href="#" class="close hidden"></a><!-- close hidden button -->
</figure>
<div class="card-content">
<h2 class="card-title">Attwood Hits Back At Rumours Of Dani Dyer Fued</h2>
<p class="category">Gossip</p>
</div><!-- .card-content -->
</article><!-- .card -->
</div>
</section>

最新更新