Кнопка увеличения JavaScript увеличивается только один раз - PullRequest
0 голосов
/ 29 апреля 2018

Я новичок в 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);
        }
    }
}

Спасибо!

1 Ответ

0 голосов
/ 29 апреля 2018

Задача

кнопки плюс / минус inc / уменьшены только один раз, и дальше идти не будут.

Explination

После изменения значения это просто число в переменной, плавающей в консоли, поскольку это последний оператор, который имеет какое-либо отношение к значению. Таким образом, только первоначальное изменение является успешным, но когда кнопки нажимаются во второй раз, функция возвращается к 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 для ссылки на элементы управления формой и альтернативные методы и свойства, которые являются лучшими версиями тех, которые используются чаще. Делегирование событий используется. Методы массива, возможно, были излишними, но мне нравится их использовать. Ниже приведены ссылки на демо, к сожалению, у фрагментов стека нет номеров строк. Plunker - index.html и README.md можно прочитать вместе с номерами строк.

HTMLFormControlsCollection


  • 52 Объявить <form>,

  • 53 Ссылка на все элементы управления формы,

  • 92-95 Создать очень короткие ссылки на каждый элемент управления формы,

  • 96-99 Создать ссылки на их значения и преобразовать их в числа,

  • 102-103, 109-110 Простые и короткие выражения,

  • 122 Общая стоимость

Шаблонные литералы


  • 75-83 Улучшено расположение элементов списка с использованием семантических элементов. Каждому элементу присваивается уникальный # id,

  • 92-94 Гибкая ссылка на #ids по результатам 89 и 90.

Методы массива


  • 90-91 При планировании конкретной стратегии присвоения имен: abc-0, split('-').pop() возвращает номер конца идентификатора и split('-').shift() возвращает буквы перед тире,

  • 113-120 Сбор всего .prc; map() возвращает массив итоговых цен; reduce() возвращает общую сумму;

Делегирование события / объект события


  • 52 Ссылка на <form>,

  • 54 Зарегистрируйте <form> для щелчка по событиям. Это единственный необходимый EventListener, он будет работать для всех его потомков / потомков,

  • 88-91, 100 Ссылка на источник события со свойством Event.target определяет не только выбранный элемент, но и другие элементы, такие как братья и сестры, родители / предки и дети / потомки.

Разное


  • 56-71 Похоже, basket это массив объектов? Не видел его в ОП, поэтому мне пришлось угадывать. Убрано свойство 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>
...