JS 可编辑表格的实现

发布于 2021-05-08  477 次阅读


1、实现效果

用户点击语文,数学,英语部分的单元格,可以实现分数的编辑,总分也会随之变化。先看下效果,如图:

在这里插入图片描述

2、设计思路

  • 先通过HTML5+CSS3绘制表格,添加input的样式和err提示动画。
  • 给要修改的数据的单元格添加name属性,给总分那一列的单元格添加rname属性。先获取所有要更改数据的单元格,通过for循环遍历,给他们添加单击事件。
  • 定义一个addAnimate方法,表示单元格输入错误时的动画提示
  • 定义setCellCilck方法,给单元格添加点击事件
  • 定义一个updateCell()方法,里面传入一个ele参数。先要获取旧的数据并保存为oldhtml。然后创建一个input标签,并传入oldhtml。在input标签的聚焦事件中判断输入的input值是否合法,若不合法,则调用addAnimate()方法弹出error标签的错误提示信息,若合法,则直接赋给单元格当前输入的值。
  • 定义一个updateScore方法,用来计算分数。通过class取出每行的分数的值,再取出总成绩的值。每个人总成绩等于每行分数相加。

3、实现源码

table.html


<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">
    <title>table</title>
</head>
<link rel="stylesheet" href="table.css">

<body>
    <div id="tableBox">
        <h2 class="title">可编辑表格</h2>
        <div class="err">成绩输入有误,请重新输入!</div>
        <table class="table">
            <thead>
                <tr>
                    <th>学号</th>
                    <th>姓名</th>
                    <th>语文</th>
                    <th>数学</th>
                    <th>英语</th>
                    <th>总分</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>1101</td>
                    <td>小王</td>
                    <td name="grade">98</td>
                    <td name="grade">80</td>
                    <td name="grade">91</td>
                    <td rname="allgrade">269</td>
                </tr>
                <tr>
                    <td>1102</td>
                    <td>小曾</td>
                    <td name="grade">88</td>
                    <td name="grade">87</td>
                    <td name="grade">92</td>
                    <td rname="allgrade">267</td>
                </tr>
                <tr>
                    <td>1103</td>
                    <td>小赵</td>
                    <td name="grade">75</td>
                    <td name="grade">90</td>
                    <td name="grade">86</td>
                    <td rname="allgrade">251</td>
                </tr>
                <tr>
                    <td>1104</td>
                    <td>小周</td>
                    <td name="grade">65</td>
                    <td name="grade">81</td>
                    <td name="grade">83</td>
                    <td rname="allgrade">229</td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
<script src="table.js"></script>

</html>

table.css

* {
    margin: 0;
    padding: 0;
    --border: 2px solid rgba(121, 121, 121, 1);
}

#tableBox {
    position: relative;
    user-select: none;
}

.table {
    margin: 0 auto;
    border-spacing: 0;
    border-collapse: collapse;
    text-align: center;
    margin-top: 47px;
    z-index: 1;
}

.err {
    display: none;
    top: 95px;
    width: 160px;
    position: absolute;
    margin-left: -100px;
    left: 50%;
    text-align: center;
    padding: 15px 18px;
    background: orange;
    border-radius: 5px;
    font-size: 13px;
    font-weight: 600;
    transition: top 1s;
    z-index: -1;
}

.movedown {
    top: 95px;
    animation: movedown 3s;
}

@keyframes movedown {
    0% {
        top: 95px
    }

    50% {
        top: 48px
    }

    100% {
        top: 95px
    }
}

.title {
    text-align: center;
    padding: 8px 0;
}

tr,
td,
th {
    border: var(--border)
}

th {
    font-weight: 600;
    text-align: center;
    background-color: rgba(204, 204, 204, 1);
}

td>input {
    width: 100px;
    height: 45px;
    border: none;
    font-size: 16px;
}

.table>thead>tr>th,
.table>tbody>tr>td {
    width: 100px;
    height: 45px;
    font-size: 16px;
}

.table>thead>tr {
    font-family: '宋体';
}

button {
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
    user-select: none;
    border: 1px solid transparent;
    border-radius: 4px;
    cursor: pointer;
    padding: 10px 12px;
    font-size: 14px;
    text-align: center;
}

table.js:

var stutable = document.getElementsByClassName("table")[0]
var grades = document.getElementsByName("grade")
var thetips = document.getElementsByClassName("err")[0]
var trs = document.getElementsByTagName("tr")

// 给单元格添加点击事件
function setCellCilck() {
    for (let i = 0; i < grades.length; i++) {
        grades[i].onclick = function () {
            updateCell(this)
        }
    }
}
setCellCilck()

// 更新单元格内容
function updateCell(ele) {
    if (document.getElementsByClassName("active-input").length == 0) {
        var oldhtml = ele.innerHTML;
        ele.innerHTML = '';
        var newInput = document.createElement('input');
        newInput.setAttribute("class", "active-input")
        newInput.value = oldhtml;
        newInput.onblur = function () {
            if (!(Number(this.value)) || this.value > 100 || this.value < 0) {
                console.log("err")
                addAnimate()
                thetips.style.display = "block"
                return
            } else {
                thetips.style.display = "none"
                ele.innerHTML = this.value == oldhtml ? oldhtml : this.value;
                updateScore()
            }
        }
        newInput.select()
        ele.appendChild(newInput);
        newInput.focus()
    } else {
        return
    }

}

// 更新总成绩
function updateScore() {
    for (let n = 1; n < trs.length; n++) {
        var grade01 = grades[n].parentNode.parentNode.children[n - 1].querySelectorAll("td[name]")
        var grade02 = grades[n].parentNode.parentNode.children[n - 1].querySelectorAll("td[rname]")
        var sum = 0
        for (let i = 0; i < grade01.length; i++) {
            sum += parseFloat(grade01[i].innerHTML)
            for (let j = 0; j < grade02.length; j++) {
                grade02[j].innerHTML = sum
            }
        }
    }
}
updateScore()

// 添加动画
function addAnimate() {
    thetips.className = "err movedown"
}

4、总结

  • 通过Name,className,parentNode,querySelectorAll等方法来获取节点。
  • 通过createElement来创建节点。
  • 通过setAttribute来设置节点属性。

活的像诗一样