可编辑表格

组件化的可编辑数据表格

设计思路

可编辑表格中的数据来自于服务端,由 JSON 格式表示。实质上就是在编辑表格数据时,异步更新 json 文件中的数据。

实现方法

服务端数据
通过 json-server 来模拟后台数据接口

1.先项目目录中创建一个 data.json 文件,存放表格中显示的数据

{
  "student": [
    {
      "id": 1008,
      "name": "李明",
      "yw": "100",
      "sx": 55,
      "yy": 66
    },
    {
      "id": 1009,
      "name": "阿梅",
      "yw": 50,
      "sx": "50",
      "yy": 99
    },
    {
      "id": 1010,
      "name": "阿四",
      "yw": "90",
      "sx": 80,
      "yy": 80
    }
  ]
}

2.在 data.json 文件目录下启动服务 json-server --watch data.json

如何实现异步更新数据呢?我们想到的解决方法就是通过 ajax 请求来实现异步操作。

核心 JS 代码设计
除了基本的 html(表格页面)和 css(表格样式)

主要的 js 分为三个类 table,student,tips

table 类:用来渲染表格。
通过 async 函数封装 ajax 中的 GET 请求获取 json 文件中的学生数据,

async getUserData() {
        var url = "http://localhost:3000/student";
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url, false);
        xhr.send();
        if (xhr.status === 200) {
            var studentsData = JSON.parse(xhr.responseText);
            var student;
            new Tips("加载成功!!", Tips.TipsClassName.success).showTips();
            for (student of studentsData) {
                this.students.push(new Student(student));
            }
        } else {
            new Tips("加载失败!!", Tips.TipsClassName.error).showTips();
            console.error('Error: ' + xhr.status);
        }
    }

加载表格中的数据

 //加载数据
    async loadUserTable() {
        var that = this;
        var userData = this.students;
        var tbody = document.getElementById("tbody");
        var innerHtml = "";
        var student;
        for (student of userData) {
            innerHtml += `
                <tr>
                    <td data-id="${student.id}">${student.id}</td>
                    <td name="name" data-id="${student.id}" >${student.name}</td>
                    <td name="grade" data-id="${student.id}" data-name="yw">${student.yw}</td>
                    <td name="grade" data-id="${student.id}" data-name="sx">${student.sx}</td>
                    <td name="grade" data-id="${student.id}" data-name="yy">${student.yy}</td>
                    <td rname="allgrade" data-id="${student.id}">${student.getAllNum()}</td>
                    <td rname="allgrade"><button id="studentDelBtn${student.id}" data-id="${student.id}">删除</button></td>
                </tr>`;
        }
        tbody.innerHTML = innerHtml;

绑定删除的点击事件

//事件绑定
for (student of userData) {
  document.getElementById(`studentDelBtn${student.id}`).onclick =
    function () {
      that.delStudent(this.dataset.id);
    };
}

给单元格添加点击事件,触发更新单元格内容的函数。

 // 给单元格添加点击事件
    async setCellCilck() {
        var that = this;
        var grades = document.getElementsByName("grade");
        var names = document.getElementsByName("name");
        for (let i = 0; i < grades.length; i++) {
            grades[i].onclick = function () {
                that.updateCell(this);
            };
        }
        for (let i = 0; i < names.length; i++) {
            names[i].onclick = function () {
                that.updateCell(this);
            };
        }
    }

更新单元格内容函数中,给不同的可编辑列提供修改规则

 // 更新单元格内容
    async updateCell(ele) {
        var that = this;
        if (document.getElementsByClassName("active-input").length == 0) {
            var oldhtml = ele.innerHTML;
            ele.innerHTML = "";
            // 通过DOM API 创建input元素,设置属性,值,方法
            var newInput = document.createElement("input");
            newInput.setAttribute("class", "active-input");
            newInput.value = oldhtml;
            newInput.onblur = function () {
                var name = ele.getAttribute("name");
                if (name == "name") {
                    const isValid = /^[\u4e00-\u9fa5]+$/.test(this.value);
                    if (isValid) {
                        //修改数据
                        ele.innerHTML = this.value;
                        //修改对象
                        const id = ele.dataset.id;
                        that.updStudent(id, { name: this.value });
                    } else {
                        new Tips("请正确输入您的姓名!", Tips.TipsClassName.error).showTips();
                        ele.innerHTML = oldhtml;
                    }
                } else if (name == "grade") {
                    const isValid = /^(\d|[1-9]\d|100)(\.\d+)?$/.test(this.value);
                    if (isValid) {
                        //修改数据
                        ele.innerHTML = this.value;
                        //修改对象
                        const id = ele.dataset.id;
                        var data = {};
                        data[ele.dataset.name] = this.value;
                        //按断文案
                        that.updStudent(id, data);
                    } else {
                        new Tips("请输入0-100!", Tips.TipsClassName.error).showTips();
                        ele.innerHTML = oldhtml;
                    }
                }
            };
            newInput.select();
            ele.appendChild(newInput);
            newInput.focus();
        } else {
            return;
        }
    }

通过 getAttribute()获取属性,
当属性值为 name 时修改姓名,再通过正则表达式/[1]+$/.test(this.value),来判断输入的值是否为中文,
TRUE 则修改当前数据,并修改对象;
FALSE,则调用 Tips 类,显示错误信息,并返回原来的值。
修改其他数据同理。

更新单元格函数中调用的 更新学生信息函数 以及 删除学生信息函数 都是通过检验 id 是否与 json 数据中学生 id 匹配来调用 student 类中的更新或删除方法。
student 类:json 数据封装,获取请求(PUT,DELETE)

constructor({ id, name, yw, sx, yy }) {
    this.id = id;
    this.name = name;
    this.yw = parseFloat(yw);
    this.sx = parseFloat(sx);
    this.yy = parseFloat(yy);
}
getAllNum() {
    return this.sx + this.yw + this.yy;
}

修改可编辑表格信息:ajax 中的 PUT 请求

async upd(newStudent) {
    Object.assign(this, newStudent);
    var url = "http://localhost:3000/student/" + this.id;
    const xhr = new XMLHttpRequest();
    xhr.open('PUT', url);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.addEventListener("load", () => {
        if (xhr.status == 200) {
            new Tips("修改成功!!", Tips.TipsClassName.success).showTips();
        } else {
            new Tips("修改失败!!", Tips.TipsClassName.error).showTips();
        }
    });
    xhr.send(JSON.stringify(this));
}

删除数据行:DELETE 请求

   async del() {
        var url = "http://localhost:3000/student/" + this.id;
        const xhr = new XMLHttpRequest();
        xhr.open('DELETE', url);
        xhr.addEventListener("load", () => {
            if (xhr.status == 200) {
                new Tips("删除成功!!", Tips.TipsClassName.success).showTips();
            } else {
                new Tips("删除失败!!", Tips.TipsClassName.error).showTips();
            }
        });
        xhr.send();
    }

tips 类:提示信息框

export default class Tips {
  static TipsClassName = {
    error: "err movedown",
    success: "success movedown",
  };
  constructor(text = "提示框", classname = Tips.TipsClassName.error) {
    this.text = text;
    this.classname = classname;
  }
  //错误提示
  showTips() {
    var that = this;
    var thetips = document.getElementById("tips");
    thetips.innerHTML = this.text;
    thetips.className = this.classname;
    thetips.style.display = "block";
    setTimeout(function () {
      that.noneTips();
    }, 3000);
  }
  //隐藏错误提示
  noneTips() {
    var thetips = document.getElementById("tips");
    thetips.style.display = "none";
  }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值