JavaScript 增加按钮只增加一次

Posted

技术标签:

【中文标题】JavaScript 增加按钮只增加一次【英文标题】:JavaScript increase button increases only once 【发布时间】:2018-10-09 16:57:02 【问题描述】:

我是 JS 的初学者,在购物车工作。我有几个使用 ES6 模板字符串在页面中呈现的产品。到目前为止一切正常,您可以将项目添加到购物篮和购物篮并正确更新总数。我唯一遇到问题的是增加/减少按钮:它们只工作一次,如果你再次点击控制台中打印的数量保持不变。

我确实找到了其他与递增/递减函数相关的 SO 帖子,但该按钮只能工作一次,所以我认为问题与我忽略的代码中的其他内容有关。

请看下面的代码:

这是要渲染的购物车

// select ul
const shoppingCart = document.querySelector('.cart-items');

// create a li item inside ul
let billContainer = document.createElement('li');

// attach an event listener to every  li
billContainer.classList.add('list');

// create the markup for every item added to the cart
for(let j = 0; j < basket.length; j++)

    const billMarkup =  `
                <p class="prodName">$basket[j].name</p>
                <div class="button-wrapper">
                    <button type="button" name="increase" class="increase">+</button>
                    <span class="quantity">$basket[j].quantity</span>
                    <button type="button" name="decrease" class="decrease">-</button>
                </div>
                <p class="totPrice">£$basket[j].price</p>
        `;

    // add the markup to the DOM
    billContainer.innerhtml = billMarkup;
    shoppingCart.appendChild(billContainer);

这是增加/减少功能(按钮的事件监听器附加到它们的父 'li'):

// attach an event listener to every li
const li = document.querySelectorAll('.list');
li.forEach( liItem => liItem.addEventListener('click', updateBill));

// add or remove items on click
function updateBill(e)
    if(e.target.nodeName === 'BUTTON')

    // current value in the basket
    let value = parseInt(this.querySelector('.quantity').textContent);

    // if the user clicks on 'increase' button
    if(e.target.name === 'increase')
        value++;
        console.log(value);

    // if the user clicks on 'decrease' button
     else if(e.target.name === 'decrease')

         value < 1 ? value = 1 : '';
         value--;
         console.log(value);
        
    

谢谢!

【问题讨论】:

你需要将value写回DOM。 递增/递减后,必须将值设置回 span.quantity 选择器。因此,下次您获得更新的价值。也不要在父母上创建一个事件并尝试倾听孩子。而是将事件拆分为特定的子元素。 谢谢,但它并不能解决问题,因为它仍然会在您第一次点击时增加/减少。抱歉,我没有将它添加到 DOM,因为我仍在控制台中对其进行测试。 【参考方案1】:

问题

加号/减号按钮只增加/减少一次,然后就不会再进一步​​了。

说明

一旦一个值改变了,它只是一个浮动在控制台中的变量中的一个数字,因为这是与该值有任何关系的最后一条语句。所以只有初始更改是成功的,但是当第二次单击按钮时,该函数会返回到 span.quantity 并获取上次单击后从未更新的值。

解决方案

解决手头问题的最简单方法是更新span.quantity 的值:

if (e.target.name === 'increase') 
    value++;
    console.log(value);
 else if (e.target.name === 'decrease') 
    value--;
    value = value < 1 ? 1 : value;
    console.log(value);
 else 
    return false;


this.querySelector('.quantity').textContent = value;

因为您没有提供功能性或可复制的演示,所以我没有费心对其进行测试,也没有尝试抽查您的代码。重写源代码并解决问题并可能防止将来出现问题的工作量更少。


演示亮点

演示使用不同的 API 来引用表单控件以及替代方法和属性,这些方法和属性是更常用的方法和属性的更好版本。使用事件委托。数组方法可能有点矫枉过正,但我​​喜欢使用它们。下面是对演示的行项目引用,不幸的是 Stack Snippets 没有行号。 Plunker - index.html and README.md 可以与行号一起读取。

HTMLFormControlsCollection


52 声明&lt;form&gt;

53 引用所有表单控件,

92-95 为每个表单控件创建非常短的引用,

96-99 创建对其值的引用并将其转换为数字,

102-103, 109-110 简单而简短的表达,

122 总价值

Template Literals


75-83 通过使用语义元素改进了列表项的布局。每个元素都分配有一个唯一的#id,

92-94 灵活引用源自 89 和 90 结果的#id。

数组方法


90-91 通过规划特定的命名策略:abc-0split('-').pop() 返回 id 的数字结尾,split('-').shift() 返回破折号前的字母,

113-120 收集所有.prcmap() 返回总价数组; reduce() 返回总和;

Event Delegation/Event Object


52 引用&lt;form&gt;

54 注册&lt;form&gt; 以点击事件。这是唯一需要的 EventListener,它将适用于它的所有子/后代,

88-91, 100 使用 Event.target 属性引用事件的来源,不仅确定单击的元素,还确定其他元素,如兄弟姐妹、父母/祖先和子女/后代。

杂项


56-71 看起来basket 是一个对象数组?在OP中没有看到它,所以我不得不猜测。删除了 basket[j].quantity 属性,因为每个项目最初的数量为 1 更有意义。

84 insertAdjacentHTML()innerHTML 类固醇。


Plunker

演示

<!DOCTYPE html>
<html>

<head>
  <style>
    html,
    body 
      font: 400 16px/1.1 Consolas;
    
    
    legend 
      font-size: 1.3rem;
    
    
    output,
    input 
      display: inline-block;
      text-align: center;
    
    
    [id^=qty] 
      width: 1.5ch;
    
    
    [id^=prc] 
      min-width: 9ch;
    
    
    [id^=prc]::before 
      content: "= £";
    
    
    [id^=bas]::before 
      content: " x  £";
    
    
    #cart+label 
      display: inline-block;
      margin: 10px 0 0 40%;
    
    
    #total::before 
      content: " £";
    
  </style>
</head>

<body>
  <form id='cart'></form>
  <label>Total:
    <output id='total' form='cart'>0.00</output>
  </label>
  <script>
    var cart = document.forms.cart;
    var x = cart.elements;
    cart.addEventListener('click', updateBill, false);

    var basket = [
      name: "thing0",
      price: 1.99
    , 
      name: "thing1",
      price: 12.99
    , 
      name: "thing2",
      price: 21.59
    , 
      name: "thing3",
      price: 0.09
    , 
      name: "thing4",
      price: 5.99
    ];

    for (let j = 0; j < basket.length; j++) 
      var details = `
      <fieldset id="item-$j">
        <legend>$basket[j].name</legend>
        <button id="inc-$j" type="button">+</button>
        <output id="qty-$j">1</output>
        <button id="dec-$j" type="button">-</button>
        <output id="bas-$j">$basket[j].price</output>
        <output id="prc-$j" class="prc">$basket[j].price</output>
    </fieldset>
    `;
      cart.insertAdjacentHTML('beforeend', details);
    

    function updateBill(e) 
      if (e.target.type === 'button') 
        var ID = e.target.parentElement.id;
        var idx = ID.split('-').pop();
        var dir = e.target.id.split('-').shift();
        var qty = x.namedItem(`qty-$idx`);
        var bas = x.namedItem(`bas-$idx`);
        var prc = x.namedItem(`prc-$idx`);
        var sum = x.total;
        var quantity = parseInt(qty.value, 10);
        var base = parseFloat(bas.value).toFixed(2);
        var price = parseFloat(prc.value).toFixed(2);
        var total = parseFloat(sum.value).toFixed(2);
        if (dir === "inc") 
          quantity++;
          qty.value = quantity;
          prc.value = quantity * base;
         else 
          quantity--;
          if (quantity <= 0) 
            quantity = 1;
          
          qty.value = quantity;
          prc.value = quantity * base;
        
      
      var prices = Array.from(document.querySelectorAll('.prc'));

      var numbers = prices.map(function(dig, idx) 
        return parseFloat(dig.value);
      );
      var grandTotal = numbers.reduce(function(acc, cur) 
        return acc + cur;
      , 0);

      x.total.value = grandTotal.toFixed(2);
    
  </script>
</body>

</html>

【讨论】:

谢谢,这真的很有帮助。我正在努力实现的一个很好的例子。它确实有效,但需要进行更多更改。 不客气,它解决了您的问题吗?我不得不改变它,我没有看到任何实际数学的方式,我认为它是服务器端的? 是的,它解决了问题,我不得不重新安排周围的东西,但知道它有效!谢谢

以上是关于JavaScript 增加按钮只增加一次的主要内容,如果未能解决你的问题,请参考以下文章

如果多次检查正确的radiobutton,则停止分数增加

java 进程消耗内存只增不减

如何在游戏循环中只检测一次碰撞而不是连续检测碰撞?

ECC原理是啥?

清除 UIWebview 缓存

原创用纯 javascript 提高博客访问量