append()方法操作table元素时为何表现与预期不符?
现象产生的核心原因
DOM规范中,所有DOM节点都是文档树内的唯一引用,同一个节点同一时间只能在文档树中存在一个位置,无法同时出现在两个地方。
当你调用append()、prepend()、insertBefore()、after()、before()这类DOM插入方法时,如果传入的节点已经是当前文档的一部分,浏览器会自动先将该节点从它原来的位置移除,再把它插入到你指定的新位置,整个过程不会创建新的节点副本。
对你的代码的逐行逻辑解释
let tbody = grid.querySelector('tbody');:获取表格的tbody节点引用let rowsArray = Array.from(tbody.rows);:将tbody下现有的所有tr节点的引用存入数组,这一步没有创建任何新的tr节点,数组里存的就是已经渲染在页面上的那5个真实tr的引用tbody.append(...rowsArray);:逐个将数组里的tr节点插入到tbody的末尾,每个tr在插入前都会被自动从原位置移除:- 如果你没有修改过
rowsArray的顺序,最终tr的排列顺序和初始状态一致,你只会观察到“没有新增tr”的现象 - 如果你对
rowsArray做过排序、打乱顺序的操作,最终tr会按照你传入的顺序重新排列,表现为“原有tr的位置被修改”
- 如果你没有修改过
如果你确实需要追加新的tr副本
如果你预期的效果是保留原有tr的同时,在末尾追加一份一模一样的新tr,你需要先手动创建节点的深拷贝,再执行插入:
let tbody = grid.querySelector('tbody'); let rowsArray = Array.from(tbody.rows); // 对每个tr做深拷贝,参数true表示连带所有子节点、内容一起克隆 let clonedRows = rowsArray.map(tr => tr.cloneNode(true)); tbody.append(...clonedRows);
执行这段代码后,tbody下的tr数量会从5个变成10个,原有tr的位置和内容都不会发生变化。
内容的提问来源于stack exchange,提问作者Reham Ashraf
相关产品推荐
相关产品推荐

