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

JavaScript表格单元格编辑:Save按钮功能失效求助

问题:表格编辑功能中Save按钮失效

点击Edit按钮后,单元格能切换为可编辑状态,Edit/Delete按钮也能替换成Save按钮,但Save按钮点击后完全无响应,需要修复该功能。


用户提供的原代码

原JavaScript代码

function deleteButtons(btns, tdBtns) {
  for (let index = 0; index < btns.length; index += index) {
    tdBtns.removeChild(btns[index]);
  }
}

function createButtons(bool, td) {
  if (bool) {
    var Edit = document.createElement('input');
    Edit.type = "button";
    Edit.value = "Edit";
    Edit.setAttribute('onclick', 'Edit(this)');
    td.appendChild(Edit);

    var Delete = document.createElement('input');
    Delete.type = "button";
    Delete.setAttribute('onclick', 'Delete(this)');
    Delete.value = "Delete";
    td.appendChild(Delete);

  } else {

    var Save = document.createElement('input');
    Save.type = "button";
    Save.value = "Save";
    Save.setAttribute('onclick', 'Save(this)');
    td.appendChild(Save);
  }
}

function Add() {
  var p1 = document.getElementById("txt").value;
  const row1 = document.getElementById("row1");
  var table = document.getElementById("MyTable");



  //insert row beginning or end
  var element = document.createElement("tr");
  var table = document.getElementById("MyTable");
  table.appendChild(element);

  if (document.getElementById('input1').checked) {
    table.insertBefore(element, table.firstElementChild);

  } else if (document.getElementById('input2').checked) {
    table.lastElementChild.after(element);
  }

  var case1 = document.createElement("td");
  case1.innerHTML = p1;
  element.appendChild(case1);

  var case2 = document.createElement("td");
  element.appendChild(case2);
  createButtons(true, case2);
}


//delete:
function Delete(element) {
  element.parentNode.parentNode.parentNode.removeChild(element.parentNode.parentNode);
}


//Edit:

function Edit(element) {

  const row = element.parentNode.parentNode;
  const tdList = row.children;

  for (let index = 0; index < tdList.length - 1; index++) {
    const element = tdList[index];
    var str = element.childNodes[0].nodeValue;
    var input = document.createElement("input");
    input.type = "text";
    input.id = "edit" + (index + 1).toString();
    input.value = str;
    element.removeChild(element.childNodes[0]);
    element.appendChild(input);



  }
  const tdBtns = tdList[1];
  const btns = tdBtns.children;
  deleteButtons(btns, tdBtns);
  createButtons(false, tdBtns);
}


function Save(element) {
  const row = element.parentNode.parentNode;
  const tdList = row.children;

  /* const edit = [
      ['edit1'],
      ['edit2']
  ]; */

  const edit = [];
  for (let index = 0; index <= 1; index++) {
    edit[index] = document.getElementById("edit" + (index + 1).toString()).value;
    if (edit[index] == "") {
      alert("You must not keep textboxes empty");
      var empty = true;
    }
  }

  if (!empty) {
    for (let index = 0; index < tdList.length - 1; index++) {
      tdList[index].removeChild(tdList[index].children[0]);
      var text = document.createTextNode(edit[index]);
      tdList[index].appendChild(text);
    }
    const tdBtns = tdList[1];
    const btns = tdBtns.children;
    deleteButtons(btns, tdBtns);
    createButtons(true, tdBtns);

  }
}

原HTML代码

<h1>Table</h1>
<div id="principal">
  <div id="cntr"><input type="text" id="txt" placeholder="Element to add.">
    <input type="button" value="Add" onclick="Add()"><br><br></div>
  <form id="frm">
    Add :
    <input type="radio" name="test" id="input1"> at the beginning
    <input type="radio" name="test" id="input2"> at the end
  </form><br>
  <table id="MyTable">
    <tbody>
      <tr id="row1">
        <td id="name_row1">Element 1 </td>
        <td>
          <input type="button" id="edit_button1" value="Edit" onclick="Edit(this)">
          <input type="button" value="Supprimer" onclick="Delete(this)">
        </td>
      </tr>
  </table>
</div>

问题根源及修复方案

1. deleteButtons函数循环逻辑错误

原循环写的index += index,第一次循环index为0,之后永远是0,既不会遍历按钮,还会导致浏览器卡死。另外btns是动态HTML集合,删除元素时长度会变化,需转成数组遍历。

2. Save函数中empty变量未初始化

empty仅在输入为空时声明赋值,初始状态为undefined,!empty会被判定为true,逻辑混乱。需提前初始化empty = false。

3. 编辑框ID重复问题

原代码给编辑框设置固定ID(edit1、edit2),同时编辑多行时ID会重复,导致document.getElementById无法获取当前行的输入框。改为直接从当前行DOM节点获取输入框,无需ID。

4. 其他细节优化

  • 使用closest('tr')代替多层parentNode,代码更简洁鲁棒
  • 给默认选中的单选按钮添加checked属性,避免Add功能初始无默认值
  • 用textContent代替innerHTML,避免XSS风险

修复后的完整代码

修复后的JavaScript代码

function deleteButtons(btns, tdBtns) {
  // 转成数组遍历,避免动态集合的长度变化问题
  Array.from(btns).forEach(btn => {
    tdBtns.removeChild(btn);
  });
}

function createButtons(bool, td) {
  if (bool) {
    const EditBtn = document.createElement('input');
    EditBtn.type = "button";
    EditBtn.value = "Edit";
    EditBtn.onclick = () => Edit(EditBtn);
    td.appendChild(EditBtn);

    const DeleteBtn = document.createElement('input');
    DeleteBtn.type = "button";
    DeleteBtn.onclick = () => Delete(DeleteBtn);
    DeleteBtn.value = "Delete";
    td.appendChild(DeleteBtn);

  } else {
    const SaveBtn = document.createElement('input');
    SaveBtn.type = "button";
    SaveBtn.value = "Save";
    SaveBtn.onclick = () => Save(SaveBtn);
    td.appendChild(SaveBtn);
  }
}

function Add() {
  const p1 = document.getElementById("txt").value.trim();
  if (!p1) {
    alert("请输入要添加的内容");
    return;
  }
  
  const table = document.getElementById("MyTable");
  const row = document.createElement("tr");

  // 根据单选框位置插入行
  if (document.getElementById('input1').checked) {
    table.insertBefore(row, table.firstElementChild);
  } else {
    table.appendChild(row);
  }

  const contentTd = document.createElement("td");
  contentTd.textContent = p1;
  row.appendChild(contentTd);

  const btnTd = document.createElement("td");
  row.appendChild(btnTd);
  createButtons(true, btnTd);

  // 清空输入框
  document.getElementById("txt").value = "";
}

function Delete(element) {
  element.closest('tr').remove();
}

function Edit(element) {
  const row = element.closest('tr');
  const contentTds = row.querySelectorAll('td:not(:last-child)');

  contentTds.forEach(td => {
    const text = td.textContent.trim();
    const input = document.createElement("input");
    input.type = "text";
    input.value = text;
    td.textContent = '';
    td.appendChild(input);
  });

  const btnTd = row.querySelector('td:last-child');
  deleteButtons(btnTd.children, btnTd);
  createButtons(false, btnTd);
}

function Save(element) {
  const row = element.closest('tr');
  const contentTds = row.querySelectorAll('td:not(:last-child)');
  let empty = false;
  const values = [];

  contentTds.forEach(td => {
    const input = td.querySelector('input');
    const val = input.value.trim();
    if (!val) {
      alert("输入框不能留空");
      empty = true;
    }
    values.push(val);
  });

  if (!empty) {
    contentTds.forEach((td, index) => {
      td.textContent = values[index];
    });

    const btnTd = row.querySelector('td:last-child');
    deleteButtons(btnTd.children, btnTd);
    createButtons(true, btnTd);
  }
}

修复后的HTML代码

<h1>Table</h1>
<div id="principal">
  <div id="cntr">
    <input type="text" id="txt" placeholder="Element to add.">
    <input type="button" value="Add" onclick="Add()"><br><br>
  </div>
  <form id="frm">
    Add :
    <input type="radio" name="test" id="input1"> at the beginning
    <input type="radio" name="test" id="input2" checked> at the end
  </form><br>
  <table id="MyTable" border="1">
    <tbody>
      <tr id="row1">
        <td id="name_row1">Element 1 </td>
        <td>
          <input type="button" id="edit_button1" value="Edit" onclick="Edit(this)">
          <input type="button" value="Delete" onclick="Delete(this)">
        </td>
      </tr>
    </tbody>
  </table>
</div>

内容的提问来源于stack exchange,提问作者nigeria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:10:29