如何为具有相同类的多个元素添加计数器

3

我正在尝试重新创建WoW天赋计算器,就像这里看到的一样 - https://classicdb.ch/?talent#h

项目文件 - https://codepen.io/jjchrisdiehl/pen/gNQLgR

这是一个帮助更好理解JavaScript的项目,请避免使用任何jQuery解决方法 - 谢谢。

如果您查看HTML代码,您会发现我已将HTML设置为具有'class'为“item”的div,并且我还有另一个嵌套在“item” div内部的div,其中包含类为“points”的内容。

<div class="item two nature_wispsplode button" data-max="5">
   <div class="points"></div>
</div>
<div class="item three fire_fireball button" data-max="3">
    <div class="points"></div>
</div>

这个想法是给具有“item”类的每个div添加一个名为logMouseButton的JavaScript事件监听器。 这将监听单击并记录它是左键还是右键单击。

/* Get item div element for addEventListener*/
let itemButton = document.getElementsByClassName("item");

/* Apply logMouseButton to every itemButton */
for (var i = 0; i < itemButton.length; i++) {
  itemButton[i].addEventListener("mouseup", logMouseButton, false);
}

现在,logMouseButton的代码是从Moz页面上的MouseEvents .button中被黑客入侵的。我认为可以使用switch来管理向每个项目的个别计数器添加或减去点数。

/* Set Counter */
var counter = 0;

/* Add or subtract points based on button clicked */

function logMouseButton(e) {

/* Set the max number of clicks in points counter based off of data-max attribute */
  var maxPoints = this.getAttribute("data-max");

  if (typeof e === "object") {
    switch (e.button) {
      case 0:
        if (counter == 0 || counter < maxPoints) {
          counter = counter + 1;
        }
        document.querySelector(".item .points").innerHTML = counter;
       // alert(counter);
        break;

      case 1:
        log.textContent = "Middle button clicked.";
        break;

      case 2:
        if (counter > 0) {
          counter = counter - 1;
        }
        document.querySelector(".item .points").innerHTML = counter;
        break;
      default:
        log.textContent = `Unknown button code: ${btnCode}`;
    }
  }
}

左击增加,右击减少。如您在我的codepen项目中所见,左/右击可以使用,但仅适用于一个项目。

我的问题是——我应该如何将其分别应用于每个项目,以便它们独立地管理自己的计数器,而不受其他项目的影响?

谢谢!

注意——在klugjo的指导下,我得以让计数器正常工作。我最终记录了“points”HTML值,增加了这个值,然后再将新值添加回innerHTML:https://codepen.io/jjchrisdiehl/pen/JgXzKe

如果您有任何关于为什么这不是最佳方法或为什么其他方法更好的见解,请告诉我!

2个回答

1

您需要访问与所点击元素对应的 div。

使用 document.querySelector(".item .points") 将始终选择 DOM 中的第一个元素。

您可以使用 e.target 访问所点击的元素,由于您所需的是该元素的唯一子元素,因此可以替换

document.querySelector(".item .points").innerHTML = counter;

使用

e.target.children[0].innerHTML = counter;

然后你会遇到另一个问题,就是你的计数器是全局的,并且对所有按钮都是通用的。因此,你需要使用哈希表(JS 对象)来代替单个整数作为 counter
var counter = {};

嗨,好主意!只更改计数器的范围是否可行,还是地图必须“记住”所有单独计数器的值? - user2391365
如果您更改范围,则变量将在每次销毁。但是,例如,您可以直接从HTML div本身检索它。 - klugjo
有趣。那么,是否可以将计数器值从零开始,递增计数器,设置新值在HTML div中,然后通过再次读取特定div的值来记录新计数器值,以便每次单击时都能存储计数器的值在HTML本身中? - user2391365
是的,这是可能的。您也可以使用 e.target.children [0] .innerHTML 读取该值。该值将是一个字符串,因此请使用 parseInt 将其转换为整数。 - klugjo

0
一种方法是选择.item元素并创建一个数组来存储每个元素的计数器(即页面中.item元素的数量)。
以下是演示,其中包含一些有用的注释:

/** selecting the elements with ".item" class and declaring an array to store each element counter separately **/
const items = document.querySelectorAll('.item'),
      countArr = new Array(items.length);

/** loop through the elements and add "mouseup" listener (to ensure catching both left and right clicks) for each element  **/
 
/** 
* el: the current element from the ".item" elements collection
* i: the index of that elemnt in the collection
**/

items.forEach((el, i) => {
  countArr[i] = 0; /** initialize each array element with 0 so we can count later (new Array puts "undefined" as the array elements values) **/
  
  /** add the "mouseup" listener **/
  el.addEventListener('mouseup', e => {
    let txtCount = el.querySelector('.count'); /** selecting the "span" that contains the counter from the current elemnt (don't forget that we're looping in ".item" elements collection) **/
    if(e.which === 1) countArr[i]++; /** left click **/
    else if(e.which === 3) countArr[i]--; /** right click **/
    txtCount.textContent = countArr[i]; /** update the "span" wih the calculated counter as left click adds 1 and right click removes 1 from the counter of each element **/
  });
});
/** basic styling for the demo **/

.item {
  display: inline-block;
  margin: 15px 0;
  padding: 8px;
  border: 2px solid teal;
  user-select: none;
}

.item .count {
  display: inline-block;
  background-color: #181818;
  color: #fff;
  font-size: 1.2rem;
  font-weight: bold;
  padding: 8px;
  border-radius: 4px;
}
<div class="item">counter = <span class="count">0</span></div>
<div class="item">counter = <span class="count">0</span></div>
<div class="item">counter = <span class="count">0</span></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接