我必须使用 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)功能上有什么问题吗?
感谢您的阅读。
在我看来,通过类来制作具有自己的状态和统一逻辑的计数器更容易。
由于使用 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>