使用 forEach 渲染计数器(EJS 和 JS)

问题描述 投票:0回答:1

我必须使用 EJS 制作一个主页,其中包含产品卡,并在购物车按钮上附加了计数器。我目前正在开发一个计数器,它有两个按钮(减号和加号)和一个通过 JS 插入数字的跨度。两个按钮都有各自的类(“.minusButton”和“.plusButton”),我的空范围也有“.counterNumber”作为类属性。当计数器编号为 1 时,我还需要禁用减号按钮,一旦数字达到 10,我必须对加号按钮执行相同的操作。

我创建了一个 JS 文件来在我的 public 文件夹中的柜台上工作,并通过使用 querySelectorAll 获取他们的类来开始我的工作。

let minus = document.querySelectorAll(".minusButton")
let plus = document.querySelectorAll(".plusButton")
let numQuantity = document.querySelectorAll(".counterNumber")

我还声明了我的产品计数器的默认值。然后将其插入我首页的空白区域中。

let counter = 1

这样做后我的问题就从这里开始。如果我只使用 querySelector,则只有我的第一张卡会侦听此脚本上写入的事件,因此我选择 querySelectorAll 来捕获数组中的所有事件,以便我可以使用 forEach。我的问题是:使用这种方法循环遍历这个数组的正确方法是什么?

这就是我尝试做的。

首先,由于我的计数器编号的默认值为 1,我想创建一个函数,其中减号按钮已被禁用,直到该数字增加为止。

function disableBegins(){
    if(counter==1){
        minus.forEach((min)=>{
            min.toggleAttribute("disabled")
            min.classList.add("disabled-counter-button")
        })
    }
}

然后是我用来在文档中写入计数器编号的函数:

function showCounter(){
    numQuantity.forEach((num)=>{
        num.innerHTML=counter
    })
}

我的主要功能:

function disableMinus(){
    if(counter<=1){
        minus.forEach((min)=>{
            min.toggleAttribute("disabled")
            min.classList.toggle("disabled-counter-button")
        })
    }else if(counter>1){
        minus.forEach((meno)=>{
            min.removeAttribute("disabled")
            min.classList.remove("disabled-counter-button")
        })
        plus.forEach((plu)=>{
            plu.removeAttribute("disabled")
            plu.classList.remove("disabled-counter-button")
        })
    }
    showCounter()
}

function disablePlus(){
    if(counter>=10){
        plus.forEach((plu)=>{
            plu.toggleAttribute("disabled")
            plu.classList.toggle("disabled-counter-button")
        })
    }else if(counter<10){
        plus.forEach((ma)=>{
            plu.removeAttribute("disabled")
            plu.classList.remove("disabled-counter-button")
        })
        minus.forEach((min)=>{
            min.removeAttribute("disabled")
            min.classList.remove("disabled-counter-button")
        })
    }
    showCounter()
}

showCounter()
disableBegins()

最后是我的听众:

minus.forEach((min)=>{
    min.addEventListener("click",()=>{
        counter--
        disableMinus()
    })
})

plus.forEach((plu)=>{
    plu.addEventListener("click",()=>{
        counter++
        disablePlus()
    })
})

计数器编号已成功写入我的所有跨度标签中,并且按钮和功能正常工作,但是当我在此主页上测试我的代码后,我意识到我仍然遇到问题,因为所有计数器都已连接。如果我只点击一个按钮,所有数字都会改变,尽管我没有点击它们。我知道这显然与 forEach 方法有关,但我找不到解决方案。

如何让我的所有计数器分别对这些事件做出反应? (仅使用EJS和JS)功能上有什么问题吗?

感谢您的阅读。

javascript foreach rendering ejs addeventlistener
1个回答
0
投票

在我看来,通过类来制作具有自己的状态和统一逻辑的计数器更容易。

由于使用 DOM 树(创建元素),类构造函数变得很麻烦,但是每个这样的计数器都保证有自己的状态,并且不依赖于外部环境。

class Counter {
  #nums = 1; // begin counter
  #btnMin = document.createElement('button');
  #btnMax = document.createElement('button');
  #val = document.createElement('span');
  constructor() {
    // create conteiner
    const div = document.createElement('div');
    div.classList.add('counter')
    // init buttons
    this.#btnMin.disabled = true;
    this.#btnMin.innerText = '-';
    this.#btnMax.innerText = '+';
    // add listeners
    this.#btnMin.addEventListener('click', this.minus.bind(this));
    this.#btnMax.addEventListener('click', this.plus.bind(this));
    // pack it in a container
    div.appendChild(this.#btnMin)
    div.appendChild(this.#val);
    div.appendChild(this.#btnMax)
    // render in DOM
    document.getElementById('counters').appendChild(div);
    this.render();
  }

  minus() {
    this.#nums--;
    if (this.#nums === 1) {
      this.#btnMin.disabled = true;
    }
    if (this.#btnMax.disabled) this.#btnMax.disabled = false;
    this.render()
  }

  plus() {
    this.#nums++;
    if (this.#nums === 10) {
      this.#btnMax.disabled = true;
    }
    if (this.#btnMin.disabled) this.#btnMin.disabled = false;
    this.render();
  }

  render() {
    this.#val.innerText = this.#nums.toString();
  }
}

// run
new Counter();
new Counter();
new Counter();
.counter {
  width: 100px;
}
<div id="counters"></div>

© www.soinside.com 2019 - 2024. All rights reserved.