【问题标题】:Javascript: Highlight elements of the same classname depending on element moused overJavascript:根据鼠标悬停的元素突出显示相同类名的元素
【发布时间】:2017-08-05 12:46:57
【问题描述】:

我又带着另一个 JavaScript DOM 问题回来了。避免使用 jQuery。

我试图在 HTML 表格中选择同一类的所有元素,并在鼠标悬停时将它们突出显示为蓝色。我想突出显示与悬停元素具有相同类名的所有单元格。到目前为止,我已经为这个问题想出了两种解决方案,但都没有奏效。

解决方案一:

var cellElements = document.getElementsByTagName('td');
for (var i = 0; i < cellElements.length; i++){
  cellElements[i].addEventListener('mouseover', function(e){
    var hoveredElement = e.target;
    if (cellElements[i].className === hoveredElement.className){
      cellElements.style.color = "blue";
    }
    else {
      cellElements.style.color = "black";
    }
  })
}

解决方案二:

var cellElements = document.getElementsByTagName('td');
for (var i = 0; i < cellElements.length; i++){
  cellElements[i].addEventListener('mouseover', function(e){
    var hoveredElement = e.target;
    document.getElementsByClassName(hoveredElement.className).style.color="blue";
  })
}

HTML 片段:

<tr class="row-c tr-selected">
  <td><input type="checkbox"></input></td>
  <td class="column-a">Specification 3</td>
  <td class="column-b">Specification 3</td>
  <td class="column-c">Specification 3</td>
</tr>
<tr class="row-d tr-selected">
  <td><input type="checkbox"></input></td>
  <td class="column-a">Specification 3</td>
  <td class="column-b">Specification 3</td>
  <td class="column-c">Specification 3</td>
</tr>

我想尝试弄清楚如何在没有 jQuery 的情况下完成此操作。

【问题讨论】:

  • 您想一次性突出显示所有内容还是只突出显示悬停的那个?
  • @Kinduser 我想突出显示与悬停元素具有相同类名的所有单元格。谢谢你的问题。我将编辑这篇文章以澄清这一点。
  • HTML 代码也会很有帮助。
  • 标题具有误导性。你想比较什么?
  • 有什么理由不使用 css :hover 代替吗?我知道你想“弄清楚如何在没有 jQuery 的情况下完成这项工作”...... CSS 是在没有 jQuery 的情况下完成这项工作的一种完全有效的方法:p

标签: javascript html dom html-table dom-events


【解决方案1】:

您的第二个示例实际上非常接近,您只需要进行一些调整。

首先,千万不要在for 循环中声明函数;这样做会产生一些奇怪的副作用。您可以像这样轻松地将声明移出:

var cellElements = document.getElementsByTagName('td');
function colorSimilar (e) {
  var hoveredElement = e.target;
  document.getElementsByClassName(hoveredElement.className).style.color="blue";
}
for (var i = 0; i < cellElements.length; i++){
  cellElements[i].addEventListener('mouseover', colorSimilar)
}

其次,您正试图根据对getElementsByClassName 的调用结果修改属性style,但该结果不是单个元素,而是array-like object of all child elements which have all of the given class names。所以你想要做的是迭代那个类似数组的对象;一种简单的方法是使用标准的for 循环:

function colorSimilar (e) {
  var hoveredElement = e.target;
  var similarElements = document.getElementsByClassName(hoveredElement.className)
  for (var i = 0; i < similarElements.length; i++) {
    similarElements[i].style.color = "blue";
  }
}

(另一种方法是使用 Array.fromHTMLCollection 转换为数组,如果您的浏览器支持它,或者通常使用 forEachArray.prototype.forEach.call

第三,您可能会注意到您的元素实际上保持蓝色,即使在将鼠标悬停在一组不同的相似类名上之后也是如此。这是因为您永远不会重置颜色!一种简单的方法是迭代所有候选对象,并根据类名切换颜色:

function colorSimilar(e) {
  var hoveredElement = e.target;
  for (var i = 0; i < cellElements.length; i++) {
    if (cellElements[i].className == hoveredElement.className) {
      cellElements[i].style.color = 'blue';
    } else {
      cellElements[i].style.color = null;
    }
  }
}

您的最终结果应如下所示:

(请注意,我使用的是backgroundColor 而不是color,只是因为它是一个更有趣的例子)

var container = document.getElementById('container');
var cellElements = container.getElementsByTagName('td');

function colorSimilar(event) {
  var className = event.target.className;
  for (var i = 0; i < cellElements.length; i++) {
    if (cellElements[i].className == className) {
      cellElements[i].style.backgroundColor = 'blue';
    } else {
      cellElements[i].style.backgroundColor = null;
    }
  }
}

for (var i = 0; i < cellElements.length; i++) {
  cellElements[i].addEventListener('mouseover', colorSimilar)
}
td {
  height: 40px;
  width: 40px;
  border: 1px solid black;
}
<table id="container">
  <tr>
    <td class="one" />
    <td class="two" />
    <td class="three" />
  </tr>
  <tr>
    <td class="three" />
    <td class="one" />
    <td class="two" />
  </tr>
  <tr>
    <td class="two" />
    <td class="three" />
    <td class="one" />
  </tr>
</table>

【讨论】:

    【解决方案2】:

    您已正确绑定事件侦听器,但您只需捕获与悬停元素具有相同class 的元素并将其放入变量中。然后,使用 Array#forEach 遍历这些元素以更改它们的样式。

    var cellElements = document.getElementsByTagName('td');
    for (var i = 0; i < cellElements.length; i++) {
    
      cellElements[i].addEventListener('mouseover', function(e) {
        var elems = document.getElementsByClassName(this.className);
        Array.from(elems).forEach(v => v.style.color = 'red');
      })
      
      cellElements[i].addEventListener('mouseleave', function(e) {
        var elems = document.getElementsByClassName(this.className);
        Array.from(elems).forEach(v => v.style.color = 'black');
      })
      
    }
    <table>
    <tr class="row-c tr-selected">
      <td><input type="checkbox"></td>
      <td class="column-a">Specification 3</td>
      <td class="column-b">Specification 3</td>
      <td class="column-c">Specification 3</td>
    </tr>
    <tr class="row-d tr-selected">
      <td><input type="checkbox"></td>
      <td class="column-a">Specification 3</td>
      <td class="column-b">Specification 3</td>
      <td class="column-c">Specification 3</td>
    </tr>
    </table>

    【讨论】:

    • 不知道节点列表会接受数组方法!有趣的。 Array.from() 看起来很有用,谢谢。
    • @HannahBanana 这是一个节点列表,但这就是我使用Array.from() 函数的原因。它将节点列表(类似数组的对象)更改为数组。然后,您可以对其进行迭代! (:
    • Array.from 很好 - 除了它在 Internet Exploder 中不起作用 - 请参阅 developer.mozilla.org/en/docs/Web/JavaScript/Reference/… 以获取 polyfill
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多