You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XMLHttpRequest加载购物车后appendChild仅显示单个子元素的问题

问题分析与解决方案

嘿,我一眼就发现你遭遇的问题根源啦!你现在只有第一个商品行显示的原因很简单:DOM元素是不能被重复插入到文档中的。

你当前的代码里,每次循环都是直接把同一个sampleBody元素添加到文档片段里——但DOM节点在文档中只能存在一个位置。第一次循环时,你把sampleBody从隐藏表格移到了文档片段;第二次循环再执行html.appendChild(sampleBody),其实是把这个元素从文档片段里“挪”出来再重新放进去,等于一直在修改同一个节点的内容,最后DOM里只会留下最后一次循环修改后的那个节点(也就是倒序的第一个数据项)。


修复方案:克隆DOM节点

解决这个问题的关键是每次循环都克隆一个新的样板行节点,使用cloneNode(true)方法来完成深克隆(会复制节点本身以及所有子元素和属性)。

修改后的JavaScript代码

(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--;) { 
            // 深克隆样板行,生成新的DOM节点
            var row = sampleBody.cloneNode(true);
            // 使用新克隆的节点来填充数据
            row.querySelector('#name').innerText = data[i].name;
            row.querySelector('#price').innerText = data[i].price;
            row.querySelector('#quantity').value = data[i].quantity;
            row.querySelector('#total').innerText = data[i].total;
            html.appendChild(row); 
        } 
        while (cartBody.firstChild) { 
            cartBody.removeChild(cartBody.firstChild); 
        } 
        cartBody.appendChild(html); 
    }; 
    renderCart(data); 
})();

额外优化:避免重复ID问题

另外还有个小问题需要注意:你样板行里的id="name"、id="price"这些属性,在克隆后会在页面中出现多个相同ID的元素,这违反了HTML规范(ID必须唯一)。建议把这些ID改成class,避免冲突:

修改后的HTML样板行

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

对应修改JavaScript中的选择器

row.querySelector('.name').innerText = data[i].name;
row.querySelector('.price').innerText = data[i].price;
row.querySelector('.quantity').value = data[i].quantity;
row.querySelector('.total').innerText = data[i].total;

这样修改后,所有商品行就能正常显示,同时也符合HTML规范啦!

内容的提问来源于stack exchange,提问作者H. Pauwelyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:34:38