如何获得父div中子代的总和?

时间:2019-01-24 06:19:31

标签: javascript sum

我正在尝试将父div内的子项总和相加,但无法将数学范围限制为单亲子级的子项。

我从一个数组开始:

[
  {
    "item1-name": "item1",
    "item1-price": "$100.00",
    "item2-name": "item2",
    "item2-price": "$200.00",
    "item3-name": "item3",
    "item3-price": "300.00",
    "item4-name": "item4",
    "item4-price": "$400.00",
    "total": "$1,000.00"
  },
  {
    "item1-name": "item1",
    "item1-price": "$100.00",
    "item2-name": "item2",
    "item2-price": "$200.00",
    "item3-name": "item3",
    "item3-price": "300.00",
    "item4-name": "",
    "item4-price": "",
    "total": "$0.00"
  },
  {
    "item1-name": "item1",
    "item1-price": "$100.00",
    "item2-name": "item2",
    "item2-price": "$200.00",
    "item3-name": "",
    "item3-price": "",
    "item4-name": "",
    "item4-price": "",
    "total": "0"
  }
]

然后我用javascript将页面内容写成html

function values(row){
  return '<div class="container">' +
    '<p>' + row["item1-name"] + '<span class="value  cost">' +  
    row["item1-price"] + '</span></p>' +
    '<p>' + row["item2-name"] + '<span class="value  cost">' + 
    row["item2-price"] + '</span></p>' +
    '<p>' + row["item3-name"] + '<span class="value  cost">' + 
    row["item3-price"] + '</span></p>' +
    '<p>' + row["item4-name"] + '<span class="value  cost">' + 
    row["item4-price"] + '</span></p>' +
    '<h4>Total' + '<span class="value  total">' + row["total"] + 
    '</span></h4>' +
  '</div>';
 };

 var containers = document.getElementsByClassName("container");

 function findTotals(container){
 $.each(containers, function(){
    var sum = 0;

     $(this).children(".cost").each(function() {
         var val = $.trim( $(this).text() );

         if ( val ) {
             val = parseFloat( val.replace( /^\$/, "" ) );
             sum += !isNaN( val ) ? val : 0;
         }
      });
      alert(sum);
   });
  };

function buildRows(rows){
   var allRows = "";
   rows.forEach(function(row){
   allRows = allRows + admitTemplate(row);
   })

   document.getElementById('rowHolder').innerHTML = allRows;
   findTotals();
}

fetch('queryExport.json')
  .then(response => {
    if (response.ok){
    return response.json()
  } else {
     return Promise.reject('something went wrong!')
  }
})
.then(rows => {
  buildRows(rows);
})

.catch(error => console.log('error is', error));

问题出在findTotals函数中。我想将总和限制为每个.container div中的.cost值。 (当前总数为1900,当总数为1000、600、300时。)(当我真的想一次遍历一个.container div时,执行页面上的所有.cost值。父(.container)div范围内的功能

您可以看到总计已损坏。我的下一个目标是将总和与总价值进行比较。如果它们不匹配,我将突出显示损坏的总值,因此可以修复生成它的查询。

感谢您的指导。

2 个答案:

答案 0 :(得分:0)

您永远不会重置sum的值,因此循环的每次迭代都会添加到现有值上,而不是独立存在。

答案 1 :(得分:0)

问题出在选择器和DOM构造中:$(this).children。子代查找所有子代的DOM元素,而不是所有子代。 .cost不是.container的子元素,它是p的子元素。如果将其替换为.find,将会得到结果。

function findTotals(container) {
  $.each(containers, function() {
    var sum = 0;

    $(this).find(".cost").each(function() {
      var val = $.trim($(this).text());			
      if (val) {
        val = parseFloat(val.replace(/^\$/, ""));
        sum += !isNaN(val) ? val : 0;
      }
    });
    console.log(sum);
  });
};

这是一个同样有效的小提琴的链接-https://jsfiddle.net/z5oug908/1/

更新后的答案

因此,我对这个问题的思考越深,我越想知道您是否真的需要搜索DOM来求和。您已经在阵列中拥有了所需的所有数据。我们可以使用map,filter和reduce来计算总计,然后再像这样渲染它们:

function calculateTotals(rows) {
  return rows.map(row => {
    const rowTotal = Object.keys(row).filter(key => {
      const match = key.search(/(price)/gi)
      return match !== -1;
    }).reduce((pre, cur) => {
      let val = row[cur];
      val = parseFloat(val.replace(/^\$/, ""));
      if (val) {
        return val + pre;
      }
      return pre;
    }, 0);

    row["total"] = rowTotal;
    return row;
  })
}

应该完成的完整示例:

function calculateTotals(rows) {
  return rows.map(row => {
    const rowTotal = Object.keys(row).filter(key => {
      const match = key.search(/(price)/gi)
      return match !== -1;
    }).reduce((pre, cur) => {
      let val = row[cur];
      val = parseFloat(val.replace(/^\$/, ""));
      if (val) {
        return val + pre;
      }
      return pre;
    }, 0);

    row["total"] = rowTotal;
    return row;
  })
}

function admitTemplate(row) {
  return '<div class="container">' +
    '<p>' + row["item1-name"] + '<span class="value  cost">' +
    row["item1-price"] + '</span></p>' +
    '<p>' + row["item2-name"] + '<span class="value  cost">' +
    row["item2-price"] + '</span></p>' +
    '<p>' + row["item3-name"] + '<span class="value  cost">' +
    row["item3-price"] + '</span></p>' +
    '<p>' + row["item4-name"] + '<span class="value  cost">' +
    row["item4-price"] + '</span></p>' +
    '<h4>Total' + '<span class="value  total">' + row["total"] +
    '</span></h4>' +
    '</div>';
};


function buildRows(rows) {
  var allRows = "";
  rows.forEach(function(row) {
    allRows = allRows + admitTemplate(row);
  })

  document.getElementById('rowHolder').innerHTML = allRows;
}

fetch('queryExport.json')
  .then(response => {
    if (response.ok) {
      return response.json()
    } else {
      return Promise.reject('something went wrong!')
    }
  })
  .then(calculateTotals)
  .then(buildRows);