组件化的可编辑数据表格

1.设计思路

  • 通过HTML5+CSS3绘制表格,使用<table> 标签定义 HTML 表格
  • 通过json-server来模拟后台数据接口,在目录中创建data.json文件,存放表格中要显示的数据
  • 将JS程序设计为三个可按需导入的独立模块,table模块用来渲染表格;student类用来封装数据,使用async声明异步请求:修改和删除;tips模块指示输入错误时的动画提示

2.实现方法及核心代码

thead中tr 元素定义表格行,th 元素定义表头

tbody显示表格内容

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
    <script type="module" src="index.mjs"></script>
    <title>table</title>
</head>

<body>
    <div id="tableBox">
        <h2 class="title">学生成绩表格</h2>
        <div class="err" id="tips">成绩输入有误,请重新输入!</div>
        <table class="table">
            <thead>
                <tr>
                    <th>学号</th>
                    <th>姓名</th>
                    <th>语文</th>
                    <th>数学</th>
                    <th>英语</th>
                    <th>总分</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="tbody"></tbody>
        </table>
    </div>
</body>

</html>

async定义getUserData()函数封装GET的异步请求获取json.data中的数据 。

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);
            }
        }
        this.setCellCilck();
    }

定义setCellCilck方法,设置哪些单元格可编辑,并用两个变量获取列名,通过for循环给单元格添加点击事件。

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);
            };
        }
    }

定义updateCell方法,用于更新单元格的内容。传入ele,表示当前点击的单元格。获取旧的单元格数据并保存为oldhtml。然后创建一个input标签,并传入oldhtml。在input标签的聚焦事件中判断输入的input值是否合法,若不合法,则调用showTips方法,弹出error标签的错误提示信息,若合法,则保存当前的值。然后取出当前单元格所在行的id。然后取出当前单元格所在行的列数,然后判断新id是否等于原数组的id,若等于,则将新的值赋给它,从而实现原数组的修改,删除同理。

    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;
        }
    }

    async delStudent(id) {
        for (var student of this.students) {
            if (id == student.id) {
                student.del();
            }
        }
    }

    async updStudent(id, newStudent) {
        for (var student of this.students) {
            if (id == student.id) {
                student.upd(newStudent);
            }
        }
    }

}

删除和修改的请求代码。

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();
    }

    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));
    }
}

定义一个showTips方法,表示单元格输入错误时的动画提示。

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";
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值