购物list/how 再次添加删除item/javascript

Shopping list/how to add again removed item/javascript

这是我的 fiddle 购物清单。 https://fiddle.jshell.net/k9L4gamm/ 快完成了,我最不想做的事情是在删除项目后再次添加(这是注释的代码)。当我更改其 class,但 "else" 不想再次添加价格时,我的工作是从要支付的金额中减去项目价格。我是编码的新手,我现在正在参加编码训练营,但我找不到任何 if/else 语句无法正常工作的原因。我将非常感谢所有建议。

首先,我可以说(正如 @trincot 评论的那样)- 你真的需要验证这个服务器端

其次,您的代码很糟糕,缩进严重并且没有进行输入检查! (例如,我可以输入 "foo" 作为价格)。

也就是说,您的问题归结为 2 行代码:


  1. 您的循环条件没有考虑到您有 2 extra table 行...
    for (var z=0;z<myRow.length;z++) {
    

应该变成:

     for (var z=1;z<myRow.length-1;z++) {

(注意 0 变成了 1length 变成了 -1)。

  1. 您使用 DOM 访问 节点 而不是 元素 !

for 循环之后的下一行:

var subRow = myRow[z].lastChild;

需要:

  var subRow = myRow[z].children[myRow[z].children.length-1];

这是因为(在大多数浏览器中),lastChild 将是 text 节点,而不是最后一个 element

代码的主要问题在这一行:

        var subRow = myRow[z].lastChild; 

这为某些行提供了文本节点对象,而不是 TD 元素。并且文本节点没有 innerHTML 属性。由于您的其余代码都适用于此,因此您在计算中得到 undefined,但事情出错了。

但是,由于您已经有了在 addProduct 函数中计算总和的代码,很遗憾在 removeBtn[= 中几乎复制了该代码50=] 事件处理程序。

所以,我建议创建一个单独的函数,它将计算总数并显示出来。它将充分利用您拥有的两个代码片段,避免上述问题:

function displayTotal() {
    // Code taken from the last part of addProduct: 
    var toPay = document.getElementsByClassName("altogether");
    var suma = 0;
    for (var n=0; n<toPay.length;n++) {
        // This condition is inspired by the removeBtn click handler:  
        if (!toPay[n].parentElement.classList.contains("strike")) { 
            suma = suma + parseFloat(toPay[n].innerHTML);
        }
    }
    // Only put the total at the end, not in the loop:
    howMuch.innerHTML = parseFloat(suma);
}

虽然与您提到的问题无关,但我也建议在您开始修改 table 之前进行任何验证检查。检查空输入也是不够的。您还应该检查输入是否为数字。

考虑到这一点,您的 addProduct 函数可能如下所示:

function addProduct() {
    // Before doing anything test the input is complete:
    if (quantityInput.value == "" || isNaN(quantityInput.value)) {
        alert("Please add quantity");
        return; // and exit!
    }
    if (priceInput.value == "" || isNaN(priceInput.value)) {
        alert("Please add price");
        return; // and exit!
    }

    var removeBtn = document.createElement("button");
    removeBtn.innerHTML="Skreśl przedmiot";

    var row = table.insertRow(1);
    var cell1 = row.insertCell(0);
    var cell2 = row.insertCell(1);
    var cell3 = row.insertCell(2);
    var cell4 = row.insertCell(3);
    var cell5 = row.insertCell(4);

    cell5.classList.add("altogether");
    cell1.appendChild(removeBtn); 
    cell2.innerHTML = productInput.value
    cell3.innerHTML = parseFloat(quantityInput.value);
    cell4.innerHTML = parseFloat(priceInput.value);
    cell5.innerHTML = parseFloat(quantity.value)*parseFloat(price.value);

    removeBtn.addEventListener("click", function(event){
        this.parentElement.parentElement.classList.toggle("strike");
        displayTotal();
    });
    // Code moved to function 
    displayTotal();
}

因此您注意到 displayTotal 在两个地方被调用:添加产品之后和切换删除之后。这样你就避免了代码重复。

这是更新后的 fiddle

还有什么可以改进的地方

最好将购物车内容保存在一个变量中(一个包含具有商品、价格和数量属性的对象的数组)。这样你就不必读取 HTML 元素来找回这些数据,这不是很有效。

其次,您最好将值分配给 textContent 而不是 innerHTML。这样你就可以避免特殊字符的问题。例如,如果您的产品名称中有一个 < 字符,您会看到其中的一部分没有显示。 textContent.

不会有这个

最后,如果在实际应用中使用,购物车必须由服务器管理。这是因为一个网页,以及上面的数字很容易被客户端软件、浏览器插件等修改,所以它们是不可信任的。所有检查都必须由服务器应用程序再次完成,该应用程序还应该有一个包含正确产品价格的数据库等。

试试这个解决方案 https://fiddle.jshell.net/uja994ae/

当您删除一个项目时,您需要再次输入 0 总数。然后只增加需要计数的项目。实际上,这不是一个好的解决方案,只有我在您的代码中调整了解决方案。为了更好地工作,您需要将 total (代码中的 howMuch.innerHTML )放在一个全局变量中,并且只增加或减少 added/removed 新项目。但是好吧,要做到这一点,您需要再次执行所有代码...

 removeBtn.addEventListener("click", function(event){
       var rowToDelete = this.parentElement.parentElement;
       var myRow = document.getElementsByTagName("tr");

       rowToDelete.classList.toggle("strike");                      
       howMuch.innerHTML = "0";

       for (var z=0;z<myRow.length;z++) {
         var subRowValue = myRow[z].lastChild.innerHTML;
         if (subRowValue && !myRow[z].classList.contains("strike")) { 
            howMuch.innerHTML = parseFloat(howMuch.innerHTML)+parseFloat(subRowValue);   
          } 
       }         
});