`appendChild(htmlobject)`只将最后一个子元素附加到数据数组

时间:2018-01-17 13:07:09

标签: javascript html

我正在制作购物车,并会在XMLHttpRequest之后加载购物车内的产品。由于表格行的复杂性,我在HTML代码中提取了这些内容(在下面的代码中看到:#sampleBody。这包含行的默认标记。

当我完成请求后,我会抓取sampleBody并将其附加到cartBody。我会改变data以上的每个循环。问题是只有第一个元素可见(我向后循环)

P.S。:在下面的代码中,我只是添加代码请求后发生的事情。



(function() {
  'use strict';

  var sampleBody, cartBody;
  var data = [{
    name: "product 1",
    price: 15,
    quantity: 2,
    total: 30
  }, {
    name: "name of product 2",
    price: 10,
    quantity: 3,
    total: 30
  }]

  function init() {
    sampleBody = document.getElementById('sampleBody');
    cartBody = document.getElementById('cartBody');
  }

  init();

  var renderCart = function(data) {
    var html = document.createDocumentFragment();

    for (var i = data.length; i--;) {

      sampleBody.querySelector('#name').innerText = data[i].name;
      sampleBody.querySelector('#price').innerText = data[i].price;
      sampleBody.querySelector('#quantity').value = data[i].quantity;
      sampleBody.querySelector('#total').innerText = data[i].total;
      html.appendChild(sampleBody);
    }

    while (cartBody.firstChild) {
      cartBody.removeChild(cartBody.firstChild);
    }

    cartBody.appendChild(html);
  };
  
  renderCart(data);

})();

.hidden {
  display: none;
}

table {
  width: 100%;
}

td, th {
  border: solid 1px black;
  padding: 5px;
}

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Price</th>
      <th>Quantity</th>
      <th>Total</th>
    </tr>
  </thead>
  <tbody id="cartBody">
    <tr>
      <td colspan="4">Loading...</td>
    </tr>
  </tbody>
</table>

<table class="hidden">
  <tr id="sampleBody">
    <td id="name"></td>
    <td>€<span id="price"></span></td>
    <td>
      <button>+</button>
      <input type="text" id="quantity">
      <button>-</button>
    </td>
    <td>€<span id="total"></span></td>
  </tr>
  <table>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

问题是id属性值在有效HTML中应该是唯一的。所以你不应该使用id来做你正在做的事情。您可以使用class替代,然后筛选要为其分配文本的文本,如下所示:

for (var i = data.length; i--;) {
  sampleBody.querySelectorAll('.name')[i].innerText = data[i].name;
  sampleBody.querySelectorAll('.price')[i].innerText = data[i].price;
  sampleBody.querySelectorAll('.quantity')[i].value = data[i].quantity;
  sampleBody.querySelectorAll('.total')[i].innerText = data[i].total;
  html.appendChild(sampleBody);
}

在循环之前执行那些4 querySelectorAll实际上会更有效:

var names = sampleBody.querySelectorAll('.name');
var prices = sampleBody.querySelectorAll('.price');
var quantities = sampleBody.querySelectorAll('.quantity');
var totals = sampleBody.querySelectorAll('.total');
for (var i = data.length; i--;) {
  names[i].innerText = data[i].name;
  prices[i].innerText = data[i].price;
  quantities[i].value = data[i].quantity;
  totals[i].innerText = data[i].total;
  html.appendChild(sampleBody);
}

答案 1 :(得分:1)

您必须在foor循环语句中克隆sampleBody节点:

for (var i = data.length; i--;) {
    var node = sampleBody.cloneNode(true);
    node.setAttribute('id', node.getAttribute('id')+i);
    node.querySelectorAll('*[id]').forEach(elt => 
       elt.setAttribute('id', elt.getAttribute('id')+i)
    );
    node.querySelector('#name'+i).innerText = data[i].name;
    node.querySelector('#price'+i).innerText = data[i].price;
    node.querySelector('#quantity'+i).value = data[i].quantity;
    node.querySelector('#total'+i).innerText = data[i].total;
    html.appendChild(node);
}

我们也可以删除id并用名称属性替换它们:

HTML:

<table class="hidden">
  <tr name="sampleBody">
    <td name="name"></td>
    <td>€<span name="price"></span></td>
    <td>
      <button>+</button>
      <input type="text" name="quantity">
      <button>-</button>
    </td>
    <td>€<span name="total"></span></td>
  </tr>
  <table>

JS:

...

function init() {
    sampleBody = document.querySelector('table.hidden > tr[name="sampleBody"]');
    cartBody = document.getElementById('cartBody');
}

...

for (var i = data.length; i--;) {
    var node = sampleBody.cloneNode(true);
    node.querySelector('*[name="name"]').innerText = data[i].name;
    node.querySelector('*[name="price"]').innerText = data[i].price;
    node.querySelector('*[name="quantity"]').value = data[i].quantity;
    node.querySelector('*[name="total"]').innerText = data[i].total;
    html.appendChild(node);
}