可编辑表格

  • 一、设计思路
  • 二 、实现方法
  • 三、js核心代码实现


一、设计思路

本次代码设计的可编辑表格,核心思路是将表格划分为多个模块,每个模块负责不同的功能,模块之间松耦合,方便复用和扩展。主要模块如下:

  1. 渲染表格模块:负责将JSON数据渲染成表格,包含表头和表体。
  2. 可编辑单元格模块:判断单元格是否可编辑,如果是在单击事件中显示输入框供编辑,编辑后更新数据源。
  3. 计算总分模块:在表头添加总分列,计算每行的总分并显示。
  4. 添加操作模块:在表头添加操作列,为每行添加删除按钮,点击后删除对应行并更新数据源。
  5. 数据校验模块:在编辑单元格时判断输入值是否在0-满分之间,不在则显示错误提示。以上模块围绕表格数据的展示、编辑与交互进行拆分,每个模块职责清晰,易于维护和扩展。

二 、实现方法

  1. 使用axios获取JSON数据,并在响应成功后调用渲染表格模块。
  2. 渲染表格模块:通过DOM操作,循环数据源渲染表头和表体。
  3. 可编辑单元格模块:在单元格点击事件中,判断是否为可编辑单元格,如果是则显示输入框,输入框失焦后获取值,判断是否在0-满分范围,如果是则更新数据源并重新渲染表格。
  4. 计算总分模块:为表头添加总分列,循环表体为每行添加总分单元格,计算每行科目分数总和并显示在总分单元格中。
  5. 添加操作模块:为表头添加操作列,循环表体为每行添加删除按钮,点击删除按钮后删除对应行并在数据源中删除对应数据。
  6. 数据校验模块:在可编辑单元格模块中,判断输入值是否在0-满分范围,不在则显示错误提示框。

三、js核心代码实现

  1. 获取成绩数据
function loadData() {
  axios.get("./data.json").then((res) => {
    data = res.data;
    if (localStorage.getItem("data")) data = JSON.parse(localStorage.data);
    else {
      data = res.data;
      localStorage.data = JSON.stringify(data);
    }
    sort.innerText = localStorage.sort || sort.innerText;
    let tr = document.createElement("tr");
    data.head.forEach((e) => {
      let th = document.createElement("th");
      th.innerText = e.item;
      tr.appendChild(th);
    });
    thead.appendChild(tr);
    data.students.forEach((e) => {
      let body_tr = document.createElement("tr");
      let sum = 0;
      e.forEach((x) => {
        let td = document.createElement("td");
        td.innerText = x;
        body_tr.appendChild(td);

        if (typeof x == "number") sum += x;
      });
      e[e.length] = sum;
      let td = document.createElement("td");
      td.innerText = sum;
      body_tr.appendChild(td);
      tbody.appendChild(body_tr);
    });
    btnn();
    addClick();
    addConfigure();
    List(); //显示第一页
  });
}

2.添加表格点击事件

function addClick() {
  let index = [];
  data.head.forEach((e, i) => {
    if (e.editable) index.push(i);
  });
  var trs = document.querySelectorAll("tbody tr");
  trs.forEach((e, row) => {
    e.querySelectorAll("td").forEach((x, i) => {
      if (index.includes(i)) {
        onHover(x);
        x.onclick = function () {
          let score = x.innerText;
          input = document.createElement("input");
          input.value = score;
          if (i == 0) {
            input.value = score.toString().padStart(3, "0");
          }
          x.innerText = "";
          x.appendChild(input);
          input.focus();
          input.select();
          input.onblur = function () {
            if (
              data.head[i].pattern &&
              !RegExp(data.head[i].pattern).test(input.value)
            ) {
              document.querySelector(".error").style.display = "block";
              setTimeout(() => {
                document.querySelector(".error").style.display = "none";
              }, 2000);
            } else {
              document.querySelector(".error").style.display = "none";
              if (i === 0) {
                data.students[10 * newcurrentpage - (10 - row)][i] =
                  input.value;
              } else {
                data.students[10 * newcurrentpage - (10 - row)][i] =
                  Number(input.value) || input.value;
              }

              input.remove();
              updataHtml();
            }
          };
          input.onclick = function (e) {
            e.stopPropagation();
          };
        };
      }
    });
  });
}

3,、增添增加行和删除行的操作

//删除行
let ok = document.querySelector(".ok");
let error = document.querySelector(".error");
let del = document.querySelector(".delete");
let delBtn = document.querySelector(".del button");
let tag = false;
delBtn.addEventListener("click", () => {
  let value = del.value;
  data.students.forEach((e) => {
    if (value === e[0]) {
      tag = true;
      nowpage = Math.floor((data.students.indexOf(e) + 1) / 10) + 1;
      if ((data.students.indexOf(e) + 1) / 10 === nowpage - 1) {
        nowpage--;
      }
      if (nowpage === totalpage) {
        lastpageList.pop();
      }
      data.students.splice(data.students.indexOf(e), 1);
      btnn(nowpage);
      ok.style.display = "block";
      setTimeout(() => {
        ok.style.display = "none";
      }, 2000);
      updataHtml();
      return 0;
    }
  });
  if (!tag) {
    error.style.display = "block";
    setTimeout(() => {
      error.style.display = "none";
    }, 2000);
  } else {
    tag = false;
  }
});
//增加行
let newdata = document.querySelector(".add");
newdata.onclick = () => {
  let input = document.querySelector(".input_pop form");
  input.innerHTML = "";
  data.head.forEach((e) => {
    if (e.editable == false && e.item != "总成绩") {
      let div = document.createElement("div");
      div.innerText = e.item + ":";
      let put = document.createElement("input");
      put.setAttribute("type", "text");
      div.appendChild(put);
      input.appendChild(div);
    }
  });