对于大多数有经验的用户来说,这听起来可能是愚蠢的,甚至是微不足道的,但是我只是几个小时前才登陆前端javascript,我必须说我对insertBefore
javascript函数的行为感到有些困惑。
我的意图很简单:我有一个包含行和单元格的表,每行都有一个带有按钮的单元格,其唯一目的是复制该单元格(及其所有内容)并放置新的单元格。复制的单元格紧挨着原始单元格。
我有一个像这样的javascript函数:
// id -> the id of the table I want the row to be added
// caller -> the object of the element that called the function
function duplicateRow(id, caller)
{
const table = document.getElementById(id);
const row = caller.parentNode.parentNode; // Caller is always a button inside a cell inside a row
const clone = row.cloneNode(true);
table.insertBefore(clone, row.nextElementSibling);
}
此函数的调用方式如下(摘自我的HTML):
<tr>
<td>
<input type="text" name="competence-name">
</td>
<td>
<button name="duplicate-row-button" onclick="duplicateRow( 'competencies-table', this )"></button>
</td>
</tr>
因此,我希望每次单击“重复行”按钮时,都会创建单击该按钮的行的精确副本,并将其添加到该行之后。
我在这里的问题不是重复(做到的正确而又顺畅),而是放置新行的位置:
nextSibling
是null
)。nextSibling
)。在向DOM中添加新节点时,null
和/或nextSibling
属性是否应该更新?有强迫他们更新的方法吗?我有什么错?我的代码,我对它应该如何工作的理解?
我肯定会接受任何可能的解释/解决方案/替代方案来实现我所需要的,并在此先感谢大家!
答案 0 :(得分:1)
问题在于,初始表行包装在tbody
元素中(您可以省略它的开始和结束标签),根据表的内容模型,这是必需的。但是,当您以编程方式添加更多行时,它们会插入tbody
之外,并且您的初始行是该隐式tbody
的唯一子级,因此DOM树如下所示:
<table>
<tbody>
<tr></tr>
</tbody>
<tr></tr>
<tr></tr>
</table>
为解决此问题,我建议向克隆行的父项添加一个克隆:
function duplicateRow(caller){
const row = caller.parentNode.parentNode; // Caller is always a button inside a cell inside a row
const clone = row.cloneNode(true);
row.parentNode.insertBefore(clone, row.nextElementSibling);
}
<table id="competencies-table">
<tr>
<td>
<input type="text" name="competence-name">
</td>
<td>
<button name="duplicate-row-button" onclick="duplicateRow( this )">Duplicate</button>
</td>
</tr>
</table>