【问题标题】:How could I simplify this code? JavaScript + css3我怎样才能简化这段代码? JavaScript + css3
【发布时间】:2025-12-07 01:05:01
【问题描述】:

我对编程还很陌生,但仍然掌握编程逻辑的窍门。我浪费了几个小时试图简化这段代码,但没有雪茄。鉴于编程的基础是简化任务,我怎样才能使下面的代码更短?

var card1 = document.getElementById('card1');
var card2 = document.getElementById('card2');
var card3 = document.getElementById('card3');
var card4 = document.getElementById('card4');

// card 1
card1.addEventListener('mouseenter', function(){
    card2.classList.add('blur');
    card3.classList.add('blur');
    card4.classList.add('blur');
})

card1.addEventListener('mouseleave', function(){
    card2.classList.remove('blur');
    card3.classList.remove('blur');
    card4.classList.remove('blur');
})

// card 2
card2.addEventListener('mouseenter', function(){
    card1.classList.add('blur');
    card3.classList.add('blur');
    card4.classList.add('blur');
})

card2.addEventListener('mouseleave', function(){
    card1.classList.remove('blur');
    card3.classList.remove('blur');
    card4.classList.remove('blur');
})

// card 3
card3.addEventListener('mouseenter', function(){
    card1.classList.add('blur');
    card2.classList.add('blur');
    card4.classList.add('blur');
})

card3.addEventListener('mouseleave', function(){
    card1.classList.remove('blur');
    card2.classList.remove('blur');
    card4.classList.remove('blur');
})

// card 4
card4.addEventListener('mouseenter', function(){
    card1.classList.add('blur');
    card2.classList.add('blur');
    card3.classList.add('blur');
})

card4.addEventListener('mouseleave', function(){
    card1.classList.remove('blur');
    card2.classList.remove('blur');
    card3.classList.remove('blur');
})

提前致谢, 蒂亚戈

编辑:根据@CertainPerformance 的回答,我最终能够想出一些满足我需求的东西:

const cards = document.querySelectorAll('.modalidade__card');
const cardsArray = Array.apply(null, cards);
for (let i = 0; i < cardsArray.length; i++) {
    cardsArray[i].addEventListener('mouseenter', (e) => {
        for (let c = 0; c < cardsArray.length; c++) {
            cardsArray[c].classList.add('blur');
        };
        e.target.classList.remove('blur');
    });
    cardsArray[i].addEventListener('mouseleave', (e) => {
        for (let c = 0; c < cardsArray.length; c++) {
            if (cardsArray[c].classList.contains('blur')) {
                cardsArray[c].classList.remove('blur');
            };
        };
    });
};

【问题讨论】:

  • 第一个改进,你可以将你的对象添加到一个集合中,然后你可以使用lambas进行操作,例如var cards = [card1,card2,card3,card4];,然后在你的函数中你可以使用cards.filter(currentCard =&gt; currentCard != card1 ).forEach(filteredCard =&gt; { filteredCard.classList.add('blur') } );

标签: javascript css mouseover simplify mouseout


【解决方案1】:

您可以使用类而不是 ID 来获取所有卡片的集合。然后你可以在所有卡片的容器上使用事件委托。当输入其中一张卡片时,循环遍历集合并模糊其余部分。当剩下一张卡片时,循环遍历集合并移除模糊:

const cards = document.querySelectorAll('.card');
container.addEventListener('mouseover', (e) => {
  if (e.target.matches('.card')) {
    for (const card of cards) {
      card.classList.add('blur');
    }
    e.target.classList.remove('blur');
  }
});
container.addEventListener('mouseout', (e) => {
  if (e.target.matches('.card')) {
    for (const card of cards) {
      card.classList.remove('blur');
    }
  }
});

请注意,要使事件委托起作用,您必须使用会冒泡的事件 - mouseovermouseout 冒泡,但 mouseentermouseleave 不会。 (或者您可以遍历每张卡并使用mouseentermouseleave 为每张卡添加一个侦听器)

【讨论】:

  • 感谢您的回复!它有点工作。如果我将鼠标悬停在卡片的中间,它就不起作用。但是,如果我将它悬停在它的边界附近,它就可以工作。该卡具有内部填充。而触发该功能的卡片区域正是padding所在的位置。所以,我猜当我将鼠标悬停在中间区域时,e.target 正在被我的 html 代码中的其他元素所取代。我可以在卡片顶部添加一个透明元素作为目标。但是你的解决方案很棒。我对解决这个问题的方法更感兴趣。感谢您的洞察力!
  • 一旦鼠标进入其中一张卡片,监听器就会触发 - 鼠标越过边界后,在鼠标再次退出边界之前不应有任何变化。
  • 是的,我不知道为什么会这样。我还在努力解决:(再次感谢!
  • 我知道出了什么问题。我在函数内添加了console.log(e.target) 以查看是什么。目标被卡片内的其他元素替换,然后触发mouseout 函数。有什么想法吗?
  • @thiagopg84 如果目标被动态替换,听起来问题中缺少一些代码,对于发现原因至关重要
【解决方案2】:

您可以使用 css :hover 伪选择器代替 javascript。

.cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
  pointer-events: none;
}

li {
    pointer-events: auto;
}
.cards:hover > * {
  filter: blur(5px);
  transition: filter .1s;
}

.cards > * {
  padding: 2rem;
  margin: 8px;
  background: bisque;
}

.cards > *:hover {
  filter: none;
}
<ul class="cards">
  <li>Card 1</li>
  <li>Card 2</li>
  <li>Card 3</li>
  <li>Card 4</li>  
</ul>

【讨论】:

  • OP 想要对 没有 悬停的元素做一些事情,而其他元素之一 is 被悬停,所以我不这样做认为:hover 会起作用
  • 啊。正确的。我误读了意图。但是您仍然可以使用 :hover 和父级或兄弟级选择器来执行此操作。
  • 你不能用 CSS 倒退。例如,虽然您可以执行 .card:hover ~ .card(将规则应用于悬停卡片之后的那些),但您不能执行 .card ~ .card:hover 并将规则应用于悬停卡片后面的那些
  • @PatrickRoberts 够公平的。 OP 的帖子中没有足够的信息来确定是否需要 javascript 来解决他的问题,并且在有特定需要之前,我倾向于使用纯 css。如果 OP 想要详细说明,我可以更新或删除我的答案(这可能没有必要,因为 CertainPerformance's answer 是一个非常可靠的 js 解决方案)。
  • 抱歉,我忍不住要编辑你的 sn-p。我添加了指针事件,以便解决 Parick Roberts 指出的问题。很好的答案,恕我直言。
【解决方案3】:

例如,我们可以

var card1 = document.getElementById('card1');
var card2 = document.getElementById('card2');
var card3 = document.getElementById('card3');
var card4 = document.getElementById('card4');

var mouseenter = function(){
    if(this != card1) card1.classList.add('blur');
    if(this != card2) card2.classList.add('blur');
    if(this != card3) card3.classList.add('blur');
    if(this != card4) card4.classList.add('blur');
};
var mouseleave = function(){
    if(this != card1) card1.classList.remove('blur');
    if(this != card2) card2.classList.remove('blur');
    if(this != card3) card3.classList.remove('blur');
    if(this != card4) card4.classList.remove('blur');
};

card1.addEventListener('mouseenter', mouseenter);
card1.addEventListener('mouseleave', mouseleave);
card2.addEventListener('mouseenter', mouseenter);
card2.addEventListener('mouseleave', mouseleave);
card3.addEventListener('mouseenter', mouseenter);
card3.addEventListener('mouseleave', mouseleave);
card4.addEventListener('mouseenter', mouseenter);
card4.addEventListener('mouseleave', mouseleave);

【讨论】:

  • 当然这简化了现有的代码,但它并没有消除不必要的重复。理想的解决方案不必为四张卡中的每张卡重复相同的代码行。
  • 谢谢,德里克!这是一个非常好的解决方案,它就像一个魅力。
【解决方案4】:

试试下面的方法

const card1 = document.getElementById("card1"),
  card2 = document.getElementById("card2"),
  card3 = document.getElementById("card3"),
  card4 = document.getElementById("card4");

// onMouse Effect
const onMouse = (ele, type = "enter") => {
  ele.forEach((item) =>
    type === "enter"
      ? item.classList.add("blur")
      : item.classList.remove("blur")
  );
};
// Card 1
card1.addEventListener("mouseenter", () => onMouse([card2, card3, card4]));
card1.addEventListener("mouseleave", () =>
  onMouse([card2, card3, card4], "leave")
);
// Card 2
card2.addEventListener("mouseenter", () => onMouse([card1, card3, card4]));
card2.addEventListener("mouseleave", () =>
  onMouse([card1, card3, card4], "leave")
);
// Card 3
card3.addEventListener("mouseenter", () => onMouse([card2, card1, card4]));
card3.addEventListener("mouseleave", () =>
  onMouse([card2, card1, card4], "leave")
);
// Card 4
card4.addEventListener("mouseenter", () => onMouse([card2, card3, card1]));
card4.addEventListener("mouseleave", () =>
  onMouse([card2, card3, card1], "leave")
);
.cursor-pointer {
  cursor: pointer;
}
h1 {
  font-size: 2em;
}
.blur h1 {
  font-size: 1em;
  text-align: center;
  color: transparent;
  text-shadow: #111 0 0 15px;
  transition: 0.4s;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
      integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <section class="container">
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card1">
        <h1>Card 1</h1>
      </div>
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card2">
        <h1>Card 2</h1>
      </div>
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card3">
        <h1>Card 3</h1>
      </div>
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card4">
        <h1>Card 4</h1>
      </div>
    </section>
  </body>
</html>

【讨论】: