#原生JS 实现可编辑表格

您所在的位置:网站首页 border-collapse:collapse表示 #原生JS 实现可编辑表格

#原生JS 实现可编辑表格

2023-05-21 08:15| 来源: 网络整理| 查看: 265

原生JS 实现可编辑表格

如下图所示,是本人和小组成员共同完成的可编辑表格:

image.png

关于设计

对于表格的想象,加上大学环境的渲染,期末成绩分数表格是一个很不错且适合的主题。每一个学生的成绩都可以修改,并且对总分进行累加,同时要设置哪一些是用户可以进行编辑的。

比如一个很简单的逻辑,教师和学生只能看见学号或者姓名这些基础信息,而且学生和学号一一匹配,不可修改,所以涉及到的可以编辑的区域就只有成绩;包括总分区域也是不可编辑的,如果可以就会破坏这个表格的使用规则。

其次,当你输入的数据,不符合当前的要求,比如小数,非数值,空值,负数或者大于当前最高分的数值等等,都是该表格所不能输入的数据。对于这些数据要给用户一个提示反馈,让他们知道这些是在表格中不符合规范的数据。

最后是删除功能,如果我需要删除一个学生的信息,那么这个删除的按键还需要让当前学生行直接删除,实现学生的信息删除。

关于实现

实现这个表格的思路:

1.首先是需要有一个Json文件,用于存储学生信息和成绩

2.要进行模块化,HTML只写DOM元素,CSS只写样式,JS只写逻辑。

3.梳理思路,首先肯定是要写出大体的表格框架,就是DOM元素,写出表格头和表格体,并给一个渲染的数据容器tbody。

4.进行一些基础设置,设置一些变量和常量,并且DOM操作获取当前元素。

image.png

5.设置函数来对表格进行设置,比如数据渲染,数据修改,编辑范围,删除等。

部分核心代码展示 // 读取本地json数据 async function fetchData() { const response = await fetch('G7.json'); if (response.ok) { const data = await response.json(); title_data.push(data.t_title); grade_data.push(data.t_grades); getHtml(); } } fetchData(); 复制代码

异步函数fetchData。它使用了ES6中的async/await语法来处理异步操作。在函数中,它首先使用fetch方法获取一个名为G7.json的文件。如果获取成功,它会将文件中的数据解析为JSON格式。

function setEditable(arr) { //arr 表示可编辑的单元格 // editable 设置单元格可编辑性 var strow = stutable.rows.length// 获取表格行数 for (let i = 1; i < strow; i++) { let stcell = stutable.rows[i].cells // 获取表格列数 // console.log(stcell); arr.forEach(function (item) { if(stcell[item]) { stcell[item].setAttribute("name", "editable") } }) } setCellCilck() } 复制代码

它接受一个数组作为参数,表示可编辑的单元格。函数中使用了一个for循环来遍历表格的每一行,然后使用一个forEach循环来遍历可编辑单元格的数组。如果当前单元格是可编辑的,就给它设置一个名为"editable"的属性。

function delRow() { for (const btn of delbtns) { btn.addEventListener("click", function() { const row = this.parentNode.parentNode; const rowIndex = row.rowIndex - 1; stutable.deleteRow(rowIndex + 1); const id = row.children[0].textContent; grade_data.forEach(item => { const index = item.findIndex(obj => obj.id === id); if (index !== -1) { item.splice(index, 1); console.log("当前数据已删除"); } }); }); } } 复制代码

该函数用于删除表格中的一行数据。函数中使用了一个for循环来遍历所有的删除按钮,然后为每个按钮添加了一个点击事件监听器。当用户点击某个删除按钮时,该事件监听器会执行一些操作,包括获取该按钮所在行的索引、从表格中删除该行、从数据数组中删除该行对应的数据等。

拓展思考基于数据的Web页面设计与开发思路和方法

根据查阅的资料和自己的总结:

数据驱动:数据是Web页面设计和开发的核心,需要从数据的角度出发,分析和处理数据,实现数据的可视化和交互。 用户体验:Web页面的用户体验是设计和开发的重要目标,需要考虑用户的需求和行为,提供简洁、直观、易用的界面和功能。 可维护性:Web页面的可维护性是设计和开发的重要考虑因素,需要采用合理的代码结构和规范,保证代码的可读性和可维护性。 安全性:Web页面的安全性是设计和开发的重要保障,需要采用合理的安全策略和技术,保护用户的隐私和数据安全。

基于数据的Web页面设计和开发需要采用一系列的技术和工具,包括数据分析和处理技术、前端开发技术、后端开发技术、数据库技术、安全技术等。其中,前端开发技术是设计和开发的重要组成部分,包括HTML、CSS、JavaScript等技术,用于实现Web页面的界面和交互。

同时还要考虑浏览器的优化,浏览器渲染,浏览器性能,浏览器存储和兼容性等等。还有不同屏幕尺寸的适应,对于不同状况的人的适应,加载和响应速度等性能优化。

后端开发技术则用于实现Web页面的业务逻辑和数据处理,包括PHP、Java、Python等技术。数据库技术则用于存储和管理Web页面的数据,包括MySQL、Oracle、MongoDB等技术。安全技术则用于保护Web页面的安全性,包括SSL、HTTPS、防火墙等技术。

综上所述,基于数据的Web页面设计和开发是一种以数据为核心的设计和开发方法,它需要遵循一系列的原则和最佳实践,采用一系列的技术和工具,实现Web页面的功能和价值。

最后附上可编辑表格的全部代码:

HTML

学生成绩表 G7-学生成绩表 当前为非数值,请重新输入 超过最大输入,请重新输入 低于最小输入,请重新输入 复制代码

CSS

* { margin: 0; padding: 0; --border: 5px solid rgb(248, 248, 248); } #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; } .wrong { display: none; top: 95px; width: 300px; position: absolute; margin-left: -100px; left: 47%; text-align: center; padding: 15px 18px; background: rgb(255, 251, 34); border-radius: 5px; font-size: 20px; font-weight: 600; transition: top 1s; z-index: -1; } .wrong1 { display: none; top: 95px; width: 300px; position: absolute; margin-left: -100px; left: 47%; text-align: center; padding: 15px 18px; background: rgb(255, 70, 70); border-radius: 5px; font-size: 20px; font-weight: 600; transition: top 1s; z-index: -1; } .wrong2 { display: none; top: 95px; width: 300px; position: absolute; margin-left: -100px; left: 47%; text-align: center; padding: 15px 18px; color: #fff; background: rgb(160, 19, 19); border-radius: 5px; font-size: 20px; font-weight: 600; transition: top 1s; z-index: -1; } .movedown { top: 80px; animation: moveup 3s infinite; } @keyframes moveup { 0% { top: 95px } 50% { top: 48px } 100% { top: 48px } } .title { text-align: center; padding: 8px 0; } tr, td, th { border: var(--border) } th { font-weight: 600; text-align: center; background-color: rgb(124, 198, 255); } td>input { width: 120px; height: 45px; border: none; font-size: 20px; } .table>thead>tr>th, .table>tbody>tr>td { width: 130px; height: 45px; font-size: 16px; } .table>thead>tr { font-family: '微软雅黑'; font-weight: bolder ; } button { color: #fff; width: 130px; height: 50px; 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; } 复制代码

JS

let stutable = document.getElementsByClassName("table")[0] let stutable_title = stutable.getElementsByTagName("thead")[0].getElementsByTagName("tr")[0] // 获取th标题行 let stutable_grade = stutable.getElementsByTagName("tbody")[0] // 获取tbody let stu_trs = stutable_grade.getElementsByTagName("tr") // 获取tbody的tr标签 var title_data = [] // 存放标题数据 var grade_data = [] // 存放成绩数据 let delbtns = document.getElementsByTagName("button") var editcell = document.getElementsByName("editable") // 可编辑的单元格 var grades = document.getElementsByClassName("grade") // 需要计算的单元格 var wrongtips = document.getElementsByClassName("wrong")[0] var wrongtips1 = document.getElementsByClassName("wrong1")[0] var wrongtips2 = document.getElementsByClassName("wrong2")[0] var alltr = document.getElementsByTagName("tr") // 获取HTML中所有的tr标签 var flag; // 设置是否显示删除栏 // 读取本地json数据 async function fetchData() { const response = await fetch('G7.json'); if (response.ok) { const data = await response.json(); title_data.push(data.t_title); grade_data.push(data.t_grades); getHtml(); } } fetchData(); // 渲染DOM内容 function getHtml() { let titlekey, gradekey // 用于存放对象的key // 表头 for (item of title_data) { for (let i = 0; i < item.length; i++) { titlekey = Object.values(item[i]); // 取出表头数据 let temp_title = ` ${titlekey} ` stutable_title.insertAdjacentHTML('beforeend', temp_title); } } // 表格内容 for (item of grade_data) { for (let i = 0; i < item.length; i++) { gradekey = Object.keys(item[i]); let temp_grade = `` // console.log(gradekey); // 获取到的key数组 for (let j in gradekey) { let k = gradekey[j]; // 获取到的key值 // console.log(item[i][k]); // 取出对象中的值 // 判断是否是最后一个键名 if (j == gradekey.length - 1) { temp_grade += `${item[i][k]}` } else { temp_grade += `${item[i][k]}` } } stutable_grade.insertAdjacentHTML('beforeend', temp_grade); } } totalScoreBar() // 生成总分栏 setAllScore([2, 3, 4, 5]) // 设置需要计算总分的学科 setEditable([2, 3, 4, 5]) // 设置可编辑单元格 updateScore() // 更新总分 flag = true; // 删除栏 if (flag) actionBar()// 生成操作栏 } // 添加总分栏 function totalScoreBar() { let allscore = document.createElement("th") allscore.innerText = "总分" stutable_title.appendChild(allscore) for (let j = 0; j < stu_trs.length; j++) { let score = document.createElement("td") score.innerText = "0" stu_trs[j].appendChild(score) score.setAttribute("rname", "allgrade") } } // 添加操作栏 function actionBar() { let caozuo = document.createElement("th") caozuo.innerText = "操作" stutable_title.appendChild(caozuo) for (let k = 0; k < stu_trs.length; k++) { let caozuo2 = document.createElement("td") let btn = document.createElement("button") btn.innerText = "删除" caozuo2.appendChild(btn) stu_trs[k].appendChild(caozuo2) } delRow() // 删除当前行操作 } // 设置哪些单元格可编辑 function setEditable(arr) { //arr 表示可编辑的单元格 // editable 设置单元格可编辑性 var strow = stutable.rows.length// 获取表格行数 for (let i = 1; i < strow; i++) { let stcell = stutable.rows[i].cells // 获取表格列数 // console.log(stcell); arr.forEach(function (item) { if(stcell[item]) { stcell[item].setAttribute("name", "editable") } }) } setCellCilck() } // 设置可计算分数的表格列 function setAllScore(arr) { const stcells = Array.from(stutable.querySelectorAll('td')); stcells.forEach((cell) => { if (arr.includes(cell.cellIndex)) { cell.classList.add('grade'); } }); } // 给单元格添加点击事件 function setCellCilck() { let scorearr = [100, 100, 100, 100] // 设计单科成绩的满分 for (let i = 0; i < editcell.length; i++) { editcell[i].onclick = function () { updateCell(this, scorearr) // delRow() } } } // 更新单元格内容 function updateCell(upt, scorearr) { let scoreMax = scorearr[upt.cellIndex - 2] scoreMax = scoreMax || 100 console.log('当前科目的满分是:' + scoreMax); if (document.getElementsByClassName("active-input").length == 0) { const oriScript = upt.innerHTML; upt.innerHTML = ''; const newInput = document.createElement('input'); newInput.classList.add("active-input"); newInput.value = oriScript; newInput.onblur = function () { switch (true) { case (this.value === "" || isNaN(this.value)): console.log("wrong"); wrongError(); wrongtips.style.display = "block"; wrongtips1.style.display = "none"; wrongtips2.style.display = "none"; return; case (this.value > 100): console.log("wrong1"); wrongError2(); wrongtips1.style.display = "block"; wrongtips.style.display = "none"; wrongtips2.style.display = "none"; return; case (this.value < 0): console.log("wrong2"); wrongError3(); wrongtips2.style.display = "block"; wrongtips.style.display = "none"; wrongtips1.style.display = "none"; return; default: wrongtips.style.display = "none"; wrongtips1.style.display = "none"; wrongtips2.style.display = "none"; // 设置一个整数和小数的判断,如果大于0.5,就向上取证,如果小于就保持原样 var num = parseFloat(this.value); var intNum = parseInt(num); var decimal = num - intNum; if (decimal > 0.4) { intNum += 1; } // upt.innerHTML = this.value == oriScript ? oriScript : intNum; if (this.value == oriScript) { upt.innerHTML = oriScript; } else { upt.innerHTML = intNum; } updateScore() break; } } newInput.select() upt.appendChild(newInput); newInput.focus() } else { return } } // 添加动画 function wrongError() { wrongtips.className = "wrong movedown" } function wrongError2() { wrongtips1.className = "wrong1 movedown" } function wrongError3() { wrongtips2.className = "wrong2 movedown" } // 更新总成绩 function updateScore() { for (let n = 1; n < alltr.length; n++) { const row = alltr[n]; const numSum = Array.from(row.querySelectorAll('td[name]')); const numSum1 = Array.from(row.querySelectorAll('td[rname]')); let sum = numSum.reduce((add, td) => add + parseFloat(td.innerHTML), 0); numSum1.forEach(td => td.innerHTML = sum); } } // 删除表格行 function delRow() { for (const btn of delbtns) { btn.addEventListener("click", function() { const row = this.parentNode.parentNode; const rowIndex = row.rowIndex - 1; stutable.deleteRow(rowIndex + 1); const id = row.children[0].textContent; grade_data.forEach(item => { const index = item.findIndex(obj => obj.id === id); if (index !== -1) { item.splice(index, 1); console.log("当前数据已删除"); } }); }); } } 复制代码

JSON

{ "t_title": [ { "title_name": "学号" }, { "title_name": "姓名" }, { "title_name": "前端综合开发" }, { "title_name": "专业项目实战" }, { "title_name": "Web前端开发技术" }, { "title_name": "HTML5应用开发" } ], "t_grades": [ { "id": 2201, "Student_name": "彭姐", "web_ES6": 95, "web_HTTP": 99, "web_max": 96, "HTML":97 }, { "id": 2202, "Student_name": "霞指导", "web_ES6": 92, "web_HTTP": 80, "web_max": 96, "HTML":93 }, { "id": 2203, "Student_name": "老马", "web_ES6": 80, "web_HTTP": 80, "web_max": 81, "HTML":100 }, { "id": 2204, "Student_name": "JO科长", "web_ES6": 80, "web_HTTP": 80, "web_max": 80, "HTML":80 }, { "id": 2205, "Student_name": "琦总监", "web_ES6": 81, "web_HTTP": 81, "web_max": 81, "HTML":81 } ] } 复制代码

至此ES6的学习历程也就告一段落了,感谢我的老师对我的指导。

欢迎大佬指点。

往事暗沉不可追,来日之路光灿烂。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3