insertBefore不更新rowIndex / nextSibling属性

时间:2018-12-03 12:10:58

标签: javascript html dom html-table

对于大多数有经验的用户来说,这听起来可能是愚蠢的,甚至是微不足道的,但是我只是几个小时前才登陆前端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>

因此,我希望每次单击“重复行”按钮时,都会创建单击该按钮的行的精确副本,并将其添加到该行之后

我在这里的问题不是重复(做到的正确而又顺畅),而是放置新行的位置:

  • 第一次,当只有一行时,它被放置在末尾(因为nextSiblingnull)。
  • 第二次单击第一行上的按钮(尽管现在紧随其后是一个兄弟姐妹),新行再次再次放置在表的末尾(就像{{1} }的第一行仍为nextSibling)。
  • 以此类推(在将重复项与新添加的行混合时,甚至会发生更奇怪的放置)。

在向DOM中添加新节点时,null和/或nextSibling属性是否应该更新?有强迫他们更新的方法吗?我有什么错?我的代码,我对它应该如何工作的理解?

我肯定会接受任何可能的解释/解决方案/替代方案来实现我所需要的,并在此先感谢大家!

1 个答案:

答案 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>