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 声明<form>
,
53 引用所有表单控件,
92-95 为每个表单控件创建非常短的引用,
96-99 创建对其值的引用并将其转换为数字,
102-103, 109-110 简单而简短的表达,
122 总价值
Template Literals
75-83 通过使用语义元素改进了列表项的布局。每个元素都分配有一个唯一的#id,
92-94 灵活引用源自 89 和 90 结果的#id。
数组方法
90-91 通过规划特定的命名策略:abc-0
、split('-').pop()
返回 id 的数字结尾,split('-').shift()
返回破折号前的字母,
113-120 收集所有.prc
;
map()
返回总价数组;
reduce()
返回总和;
Event Delegation/Event Object
52 引用<form>
,
54 注册<form>
以点击事件。这是唯一需要的 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 增加按钮只增加一次的主要内容,如果未能解决你的问题,请参考以下文章