【问题标题】:How to add hover effect upon mouseover to all divs on a page?如何在鼠标悬停时为页面上的所有 div 添加悬停效果?
【发布时间】:2020-03-21 05:38:45
【问题描述】:

我有一个 16x16 的小方块网格。我添加了一个永久的“悬停”效果,当我将鼠标放在第一个框上时,它会变成红色。但是,我想为页面上的所有框添加相同的效果。我不知道该怎么做 - 我试图向整个页面添加一个事件侦听器并使用 target.nodeName 和 target.NodeValue,但无济于事。我已经包含了修复框在鼠标悬停时变为红色的工作版本。

var n=16; //take grid column value as you want

const bigContainer = document.querySelector('.bigContainer')

for(var i = 1; i < n; i++) {
    bigContainer.innerHTML+='<div class="row">';

    for(j = 0; j < n; j++) {
        bigContainer.innerHTML+='<div class="smallBox">';
    }
}

const smallBox = document.querySelector('.smallBox');

smallBox.addEventListener('mouseover', () => {
    smallBox.classList.add('permahover');
});
.smallBox {
    border: 1px solid black;
    width: 20px;
    height: 20px;
    display: inline-block;
}

.permahover {
    background: red;
}

h1 {
    text-align: center;
}

.bigContainer {
    text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">

</div>

【问题讨论】:

  • @StephenP 不是 OP,但我想 OP 希望悬停状态保持不变,因为 html 的标题是“Etch-a-Sketch Assignment”

标签: javascript html css


【解决方案1】:

您遇到的直接问题是这只是查询,然后向一个元素添加事件侦听器。

const smallBox = document.querySelector('.smallBox');

smallBox.addEventListener('mouseover', () => {
    smallBox.classList.add('permahover');
});

在上述代码部分中,querySelector 仅返回第一个匹配元素。您可能正在这里寻找querySelectorAll,它返回匹配元素的NodeList

您有两种选择(如果您想进一步重构代码,可能还有其他选择)。事实上,最简单的方法是查询所有单元格并为每个单元格添加事件侦听器。

var n=16; //take grid column value as you want

const bigContainer = document.querySelector('.bigContainer')

for(var i = 1; i < n; i++) {
    bigContainer.innerHTML+='<div class="row">';

    for(j = 0; j < n; j++) {
        bigContainer.innerHTML+='<div class="smallBox">';
    }
}

const smallBoxes = document.querySelectorAll('.smallBox');

[...smallBoxes].forEach(smallBox => {
  smallBox.addEventListener('mouseover', () => {
      smallBox.classList.add('permahover');
  });
})
.smallBox {
    border: 1px solid black;
    width: 20px;
    height: 20px;
    display: inline-block;
}

.permahover {
    background: red;
}

h1 {
    text-align: center;
}

.bigContainer {
    text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">

</div>

另一种选择是使用您确定的事件委托。这是您可以利用它的方法。注意:这种方法对于像“鼠标悬停”这样的攻击性事件有点棘手,因为您可能会得到误报目标(例如外部容器)。

var n=16; //take grid column value as you want

const bigContainer = document.querySelector('.bigContainer')

for(var i = 1; i < n; i++) {
    bigContainer.innerHTML+='<div class="row">';

    for(j = 0; j < n; j++) {
        bigContainer.innerHTML+='<div class="smallBox">';
    }
}

bigContainer.addEventListener('mouseover', e => {
  var target = e.target

  if (target !== bigContainer) {
    target.classList.add('permahover')
  }
})
.smallBox {
    border: 1px solid black;
    width: 20px;
    height: 20px;
    display: inline-block;
}

.permahover {
    background: red;
}

h1 {
    text-align: center;
}

.bigContainer {
    text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">

</div>

【讨论】:

  • 干得好!我确实建议你指出querySelectorquerySelectorAll 之间的区别——我还有一个问题:你和Leonid 都使用扩展运算符[...smallBoxes].forEach(…)——但smallBoxes.forEach(…) 的工作方式与好吧,正如 PatrykBuniX 使用的那样(以及我在考虑写答案时正在玩的那样)——所以 为什么 使用传播?
  • 嘿@StephenP,好问题。 NodeList.prototype.forEach 可能存在浏览器兼容性问题:caniuse.com/#feat=mdn-api_nodelist_foreach 并且需要 polyfill。我想您可以对 ES6 扩展语法说同样的话(尽管为此使用 Babel 更为标准)。更好的“符合 ES5”的方法是 [].forEach.cal(nodeList, callback)。不过,这更像是一种习惯,而不是答案的相关部分。我怀疑这对于试图学习基础知识的人来说是一个很大的问题(目前)。
  • 编辑添加更多关于querySelectorquerySelectorAll 的详细信息,但建议很好。
  • 啊!我明白了...我很幸运,我不必支持“旧”浏览器或任何版本的 IE,因为我在内部 Web 应用程序上工作(我们可以要求最高-日期浏览器),并且对 NodeList.forEach 的支持可以追溯到 2016-2017 年,所以我不必求助于它。
  • @Damon 就是这样!第二种方法是我想要的——我几乎在一些无效的尝试中就在那里,但没有完全正确的知识来完成它。非常感谢您的详尽解释!
【解决方案2】:

您需要使用委托事件,因为页面加载时页面上不存在所有小框(您可以在检查器元素中找出只有您的第一个框具有事件侦听器)。

所以你听整个容器(因为它总是在加载的页面上)

bigContainer.addEventListener('mouseover', () => {
    // Code for checking if we hovered a small div & if yes applying the style
});

...然后与event.target(将是悬停的小div)进行比较

if (event.target.matches('.smallBox')) {
    event.target.classList.add('permahover');
}

var n=16; //take grid column value as you want

const bigContainer = document.querySelector('.bigContainer')

for(var i = 1; i < n; i++) {
    bigContainer.innerHTML+='<div class="row">';

    for(j = 0; j < n; j++) {
        bigContainer.innerHTML+='<div class="smallBox">';
    }
}

const smallBox = document.querySelector('.smallBox');

bigContainer.addEventListener('mouseover', () => {
    if (event.target.matches('.smallBox')) {
        event.target.classList.add('permahover');
    }
});
.smallBox {
    border: 1px solid black;
    width: 20px;
    height: 20px;
    display: inline-block;
}

.permahover {
    background: red;
}

h1 {
    text-align: center;
}

.bigContainer {
    text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">

</div>

【讨论】:

    【解决方案3】:

    您可以使用forEach 方法循环遍历所有框并在每个框上添加 eventListener。 如果他们都有.smallBox 类,你可以这样做:

    const smallBoxes = document.querySelectorAll('.smallBox');
    
    smallBoxes.forEach(box => box.addEventListener('mouseover', () => {
        smallBox.classList.add('permahover');
    }))
    

    希望对你有帮助!

    【讨论】:

    • 我没有使用它作为添加永久悬停效果的解决方案,但我确实利用这种方法为网格创建了一个重置​​按钮。感谢您的帮助!
    【解决方案4】:
    let smallBoxes = document.querySelectorAll('.smallBox');
    [...smallBoxes].forEach(el => {
        el.addEventListener('mouseover', e => e.target.classList.add('permahover'));
    });
    

    【讨论】:

      【解决方案5】:

      您应该将事件侦听器设置为您的 DOM,并询问触发元素是否是您的特定类元素之一。因此,您可以使用该类处理每个元素。

      var n = 16; //take grid column value as you want
      
      const bigContainer = document.querySelector('.bigContainer')
      
      for (var i = 1; i < n; i++) {
        bigContainer.innerHTML += '<div class="row">';
      
        for (j = 0; j < n; j++) {
          bigContainer.innerHTML += '<div class="smallBox">';
        }
      }
      
      document.addEventListener('mouseover', function(e) {
        if (e.target && e.target.className == 'smallBox') {
              var target = e.target;
              target.classList.add('permahover');
        }
      });
      

      工作 js 小提琴:https://jsfiddle.net/nwukf205/

      希望我能帮助你:) 有问题就问吧

      【讨论】:

        【解决方案6】:

        您是否尝试过 :hover 选择器?不确定您是否要在此处指定任何动态操作,但很容易做一些基本的事情。

        https://www.w3schools.com/cssref/sel_hover.asp

        a:hover {
           background-color: yellow;
         }
        

        我自己没有尝试过您的示例,但此处已回答了与此类似的问题:

        Hover on element and highlight all elements with the same class

        【讨论】:

        • 这不行,当div不再悬停时样式会消失
        猜你喜欢
        • 1970-01-01
        • 2016-04-26
        • 1970-01-01
        • 1970-01-01
        • 2020-08-16
        • 1970-01-01
        • 2010-12-04
        • 2011-06-30
        • 2016-06-15
        相关资源
        最近更新 更多