JavaScript实现学生管理系统
以下是一个JavaScript实现学生管理系统的例子,包含以下几种功能:
1、页面数据全部使用数据驱动
2、刷新页面后列表中新增的信息不会被清除
3、增加功能
4、正则验证
5、重置功能
5、删除功能
6、编辑功能
css总代码
* {
margin: 0;
padding: 0;
}
.box {
width: 800px;
height: auto;
margin: 0 auto;
background-color: skyblue;
}
.box .content {
width: 100%;
margin: 0 auto;
}
.box .content h1 {
text-align: center;
margin-bottom: 20px;
}
.box .content .content_top {
width: 700px;
margin: 0 auto;
margin-top: 40px;
}
.box .content .content_top span {
color: red;
}
.box .content .content_top input {
width: 600px;
height: 40px;
margin-left: 33px;
border-radius: 15px;
border: none;
padding-left: 30px;
box-sizing: border-box;
}
.box .content .content_top .user {
margin-left: 20px;
}
.box .content .password .pwd{
margin-left: 35px;
}
.btnArr {
width: 530px;
margin: 0 auto;
margin-top: 20px;
}
.btnArr button {
width: 100px;
height: 50px;
border-radius: 10px;
border: none;
background-color: green;
color: white;
font-size: 20px;
cursor: pointer;
}
.btnArr button:nth-child(2) {
background-color: blue;
margin-left: 20px;
}
table {
width: 780px;
margin: 0 auto;
margin-top: 40px;
background-color: #fff;
}
table tr {
text-align: center;
}
table td {
width: 165px;
border-bottom: 1px solid #ccc;
}
table td input {
width: 140px;
}
table .cz button {
width: 60px;
height: 30px;
background-color: blue;
text-align: center;
line-height: 30px;
border: none;
border-radius: 8px;
cursor: pointer;
color: white;
}
table .cz button:nth-child(2) {
background-color: red;
margin-left: 15px;
}
.red {
font-size: 12px;
color: red;
}
.none {
display: none;
}
.inline {
display: '';
}
.erro1,.erro2,.erro3 {
margin-left: 140px;
}
HTML总代码
<div class="box">
<div class="content">
<h1>学生管理系统</h1>
<div class="userName content_top">
<span>*</span>用户名
<input type="text" class="user">
</div>
<span class="erro1 red none">请输入正确的用户名</span>
<div class="password content_top">
<span>*</span>密码
<input type="password" class="pwd">
</div>
<span class="erro2 red none">请输入正确的密码</span>
<div class="email content_top">
<span>*</span>邮箱
<input type="email" class="ema">
</div>
<span class="erro3 red none">请输入正确的邮箱</span>
<div class="btnArr">
<button class="add">添加</button>
<button class="res">重置</button>
</div>
</div>
<table>
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>密码</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
页面搭建完,咱们就开始写js了
1、首先获取需要用到的元素
// 获取添加按钮
var add = document.getElementsByClassName('add')[0]
// 获取用户名input框
var user = document.getElementsByClassName('user')[0]
// 获取密码input框
var pwd = document.getElementsByClassName('pwd')[0]
// 获取邮箱input框
var ema = document.getElementsByClassName('ema')[0]
// 获取tbody,需要将数据渲染到tbody中
var tbody = document.querySelectorAll('tbody')[0]
// 获取重置清空按钮
var res = document.getElementsByClassName('res')[0]
// 获取正则验证错误的元素
var erro1 = document.getElementsByClassName('erro1')[0]
var erro2 = document.getElementsByClassName('erro2')[0]
var erro3 = document.getElementsByClassName('erro3')[0]
// 获取编辑按钮
var edit = document.getElementsByClassName('edit')
2、tbody需要数据渲染的数据
let data = [
{id : 1, name : '张三', password : '666', email : 'test@qq.com', isEdit : false},
{id : 2, name : '李四', password : '777', email : 'test@qq.com', isEdit : false},
{id : 3, name : '王五', password : '888', email : 'test@qq.com', isEdit : false},
{id : 4, name : '赵六', password : '999', email : 'test@qq.com', isEdit : false}
]
3、需要渲染的数据写好了,咱们就可以开始渲染到页面上去了(此时不是完整版)
function render() {
tbody.innerHTML = ''
data.forEach((value, index) => {
tbody.innerHTML += `
<tr>
<td>${value.id}</td>
<td>
<span>${value.name}</span>
</td>
<td>
<span>${value.password}</span>
</td>
<td>
<span>${value.email}</span>
</td>
<td class="cz">
<button>编辑</button>
<button>删除</button>
</td>
</tr>
`
})
}
render()
这里有个关键的点:为什么要封装起来?
因为这些代码在后面的复用性很高,添加、删除等功能都会用到,咱们不能每次要用到的时候就复制粘贴一遍,会造成代码冗余的问题,美观性太差了,所以封装一边,然后进入页面的时候就渲染一边,也就是初始化一下页面
4、静态页面写出来了,然后就开始写功能代码了
在写添加功能前,要把添加的正则验证写出来
// 用户名正则
/*
用于验证用户名是否只包含字母和中文字符,不允许包含其他特殊字符、数字或空格。
*/
const userNameRegExp = /^[a-zA-Z\u4e00-\u9fa5]+$/
// 密码正则
/*
密码至少包含一个小写字母。
密码至少包含一个大写字母。
密码至少包含一个数字。
密码长度至少为8个字符
*/
const pwdRegExp = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/
// 邮箱正则
/*
一个或多个字母、数字或破折号(-)组成的用户名。
一个或多个以点(.)结尾的字符串,其中点之前的字符可以是字母、数字或破折号(-)。
一个字母、数字组成的域名,域名以点(.)结尾。
一个顶级域名,如 .com、.org 等。
*/
const emaRegExp = /^[\w-]+(\.[\w-]+)*@([a-zA-Z0-9-]+\.)+(com|org|net|edu|gov|co|io|info|biz|me|us)$/
4.1、添加功能
add.onclick = function () {
let flag = true;
// 用户名验证不通过,直接退出
// 判断用户名是否为非空 和 用户名正则是否返回true,
if(!user.value || !(userNameRegExp.test(user.value))) {
// 用户名为空或者正则返回false,执行以下代码,代表验证失败
erro1.classList.remove('none')
erro1.classList.add('inline')
flag = false
} else {
// 用户名不为空和正则返回true,执行以下代码,代表验证成功
erro1.classList.remove('inline')
erro1.classList.add('none')
console.log(erro1.classList);
}
// 密码验证不通过,直接退出
if(!pwd.value || !pwdRegExp.test(pwd.value)) {
erro2.classList.remove('none')
erro2.classList.add('inline')
flag = false
} else {
erro2.classList.add('none')
erro2.classList.remove('inline')
}
// 邮箱验证不通过,直接退出
if(!ema.value || !emaRegExp.test(ema.value)) {
erro3.classList.remove('none')
erro3.classList.add('inline')
flag = false
} else {
erro3.classList.add('none')
erro3.classList.remove('inline')
}
if (!flag) { // 如果校验不通过就不执行后面代码
return false // 提前退出
}
// 获取到需要添加的数据,因为data数据中是一个一个对象,所以要放在一个对象中
let obj = {
id : data.length+1,
name : user.value,
password : pwd.value,
email : ema.value
}
// 将这个对象添加到数据中
data.push(obj)
// 点击提交按钮,重置input框
resRender()
// 重新渲染页面
render()
}
因为我们操作的是数据驱动,首先要清楚自己写的数据驱动中有什么,是什么格式,咱们的数据驱动的格式就很明了,就是数组包对象的格式,最外面是一个数组,里面的内容是一个一个的对象,所以点击添加按钮的时候,就是把一个新的对象push进原数组data中。
最重要的一点就是添加功能写完了,别忘了重新渲染一下页面,不然页面上没有任何改动,也就是调用一下render函数
4.2、重置功能
// 封装清空方法
function resRender() {
user.value = ''
pwd.value = ''
ema.value = ''
}
// 重置功能
res.onclick = () => {
resRender()
}
点击重置按钮调用清空功能函数,重置input框,因为点击添加按钮的时候input框也会重置,所以封装了一个清空功能
4.3、删除功能
function del(id) {
data.forEach((value, index) => {
if(value.id === id) {
if(confirm('是否删除')) {
data.splice(index,1)
}
}
})
render()
}
del函数在哪里调用呢,render函数中给删除按钮绑定一个del的函数调用,并把data中的id传进去,此时render中的数据要开始写东西了
function render() {
tbody.innerHTML = ''
data.forEach((value, index) => {
tbody.innerHTML += `
<tr>
<td>${value.id}</td>
<td>
<span>${value.name}</span>
</td>
<td>
<span>${value.password}</span>
</td>
<td>
<span>${value.email}</span>
</td>
<td class="cz">
<button>编辑</button>
<button onclick='del(${value.id})'>删除</button>
</td>
</tr>
`
})
}
拿到传进来的id,判断点击的按钮的id是不是和data数据中的id一致,一致的话就代表找到了要删除的data数据;如果点击确认就删除原数组data中当前id的那一条数据;然后再重新渲染页面
4.4、本地存储功能
function hendleSetStorage(key, data) {
window.localStorage.setItem(key, JSON.stringify(data))
}
function hendleGetStorage(key) {
return JSON.parse(window.localStorage.getItem(key)) || []
}
刷新页面后,新增的数据不会消失,这时候就是localStorage登场的时候了,但是,这还是一个函数,这个时候就要考虑,首次渲染页面的时候,判断本地存储中存不存在数据,如果不存在的话咱们就渲染我们写的data数据,所以在写data数据时,要加上一个判断,此时data变成了以下这样
let data = hendleGetStorage('data').length ? hendleGetStorage('data') : [
{id : 1, name : '张三', password : '666', email : 'test@qq.com', isEdit : false},
{id : 2, name : '李四', password : '777', email : 'test@qq.com', isEdit : false},
{id : 3, name : '王五', password : '888', email : 'test@qq.com', isEdit : false},
{id : 4, name : '赵六', password : '999', email : 'test@qq.com', isEdit : false}
]
4.5、编辑功能
function handleEditStudent() {
let edit = document.getElementsByClassName('edit')
let edit1 = [...edit]
edit1.forEach(v => {
v.addEventListener('click', function() {
let type = this.dataset.type;
let id = this.dataset.id;
let index = this.dataset.index;
data.forEach(item => {
if(+id === item.id) {
item.isEdit = type !== 'ok'
type === 'ok' && (item.name = document.getElementsByClassName('user-name-input')[index].value)
type === 'ok' && (item.password = document.getElementsByClassName('user-pwd-input')[index].value)
type === 'ok' && (item.email = document.getElementsByClassName('user-email-input')[index].value)
}
})
render()
})
})
}
点击编辑按钮,当前行的学生数据切换成可修改的input框,并且同步显示该学生的信息
点击编辑按钮,会变成确定按钮,样式会变成绿色
点击确认按钮,会把修改后的值,覆盖之前的值
此时,render函数中就变成以下的样子
function render() {
tbody.innerHTML = ''
data.forEach((value, index) => {
tbody.innerHTML += `
<tr>
<td>${value.id}</td>
<td>
<input class="user-name-input" style="display: ${value.isEdit ? '' : 'none'};" value="${value.name}" />
<span style="display: ${value.isEdit ? 'none' : ''};">${value.name}</span>
</td>
<td>
<input class='user-pwd-input' style="display: ${value.isEdit ? '' : 'none'};" value="${value.password}" />
<span style="display: ${value.isEdit ? 'none' : ''};">${value.password}</span>
</td>
<td>
<input class='user-email-input' style="display: ${value.isEdit ? '' : 'none'};" value="${value.email}" />
<span style="display: ${value.isEdit ? 'none' : ''};">${value.email}</span>
</td>
<td class="cz">
<button style="background: ${value.isEdit ? 'green' : 'blue'};" class="edit" data-id="${value.id}" data-type="${value.isEdit ? 'ok' : 'edit'}" data-index="${index}" >${value.isEdit ? '完成' : '编辑'}</button>
<button onclick='del(${value.id})'>删除</button>
</td>
</tr>
`
handleEditStudent()
hendleSetStorage('data', data)
})
}
5、完整版的js
// 获取添加按钮
var add = document.getElementsByClassName('add')[0]
// 获取用户名input框
var user = document.getElementsByClassName('user')[0]
// 获取密码input框
var pwd = document.getElementsByClassName('pwd')[0]
// 获取邮箱input框
var ema = document.getElementsByClassName('ema')[0]
// 获取tbody,需要将数据渲染到tbody中
var tbody = document.querySelectorAll('tbody')[0]
// 获取重置清空按钮
var res = document.getElementsByClassName('res')[0]
var erro1 = document.getElementsByClassName('erro1')[0]
var erro2 = document.getElementsByClassName('erro2')[0]
var erro3 = document.getElementsByClassName('erro3')[0]
var edit = document.getElementsByClassName('edit')
// 1、tbody需要数据渲染的数据
let data = hendleGetStorage('data').length ? hendleGetStorage('data') : [
{id : 1, name : '张三', password : '666', email : 'test@qq.com', isEdit : false},
{id : 2, name : '李四', password : '777', email : 'test@qq.com', isEdit : false},
{id : 3, name : '王五', password : '888', email : 'test@qq.com', isEdit : false},
{id : 4, name : '赵六', password : '999', email : 'test@qq.com', isEdit : false}
]
// 封装清空方法
function resRender() {
user.value = ''
pwd.value = ''
ema.value = ''
}
// 用户名正则
/*
这个正则表达式用于验证用户名是否只包含字母和中文字符,不允许包含其他特殊字符、数字或空格。
*/
const userNameRegExp = /^[a-zA-Z\u4e00-\u9fa5]+$/
// 密码正则
/*
密码至少包含一个小写字母。
密码至少包含一个大写字母。
密码至少包含一个数字。
密码长度至少为8个字符
*/
const pwdRegExp = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/
// 邮箱正则
/*
一个或多个字母、数字或破折号(-)组成的用户名。
一个或多个以点(.)结尾的字符串,其中点之前的字符可以是字母、数字或破折号(-)。
一个字母、数字组成的域名,域名以点(.)结尾。
一个顶级域名,如 .com、.org 等。
*/
const emaRegExp = /^[\w-]+(\.[\w-]+)*@([a-zA-Z0-9-]+\.)+(com|org|net|edu|gov|co|io|info|biz|me|us)$/
// 页面渲染封装,初始化操作
function render() {
tbody.innerHTML = ''
data.forEach((value, index) => {
tbody.innerHTML += `
<tr>
<td>${value.id}</td>
<td>
<input class="user-name-input" style="display: ${value.isEdit ? '' : 'none'};" value="${value.name}" />
<span style="display: ${value.isEdit ? 'none' : ''};">${value.name}</span>
</td>
<td>
<input class='user-pwd-input' style="display: ${value.isEdit ? '' : 'none'};" value="${value.password}" />
<span style="display: ${value.isEdit ? 'none' : ''};">${value.password}</span>
</td>
<td>
<input class='user-email-input' style="display: ${value.isEdit ? '' : 'none'};" value="${value.email}" />
<span style="display: ${value.isEdit ? 'none' : ''};">${value.email}</span>
</td>
<td class="cz">
<button style="background: ${value.isEdit ? 'green' : 'blue'};" class="edit" data-id="${value.id}" data-type="${value.isEdit ? 'ok' : 'edit'}" data-index="${index}" >${value.isEdit ? '完成' : '编辑'}</button>
<button onclick='del(${value.id})'>删除</button>
</td>
</tr>
`
handleEditStudent()
hendleSetStorage('data', data)
})
}
render() // 进入页面首次渲染,所以要调用一下
// 添加功能
add.onclick = function () {
let flag = true;
// 用户名验证不通过,直接退出
// 判断用户名是否为非空 和 用户名正则是否返回true,
if(!user.value || !(userNameRegExp.test(user.value))) {
// 用户名为空或者正则返回false,执行以下代码,代表验证失败
erro1.classList.remove('none')
erro1.classList.add('inline')
flag = false
} else {
// 用户名不为空和正则返回true,执行以下代码,代表验证成功
erro1.classList.remove('inline')
erro1.classList.add('none')
console.log(erro1.classList);
}
// 密码验证不通过,直接退出
if(!pwd.value || !pwdRegExp.test(pwd.value)) {
erro2.classList.remove('none')
erro2.classList.add('inline')
flag = false
} else {
erro2.classList.add('none')
erro2.classList.remove('inline')
}
// 邮箱验证不通过,直接退出
if(!ema.value || !emaRegExp.test(ema.value)) {
erro3.classList.remove('none')
erro3.classList.add('inline')
flag = false
} else {
erro3.classList.add('none')
erro3.classList.remove('inline')
}
if (!flag) { // 如果校验不通过就不执行后面代码
return false // 提前退出
}
// 获取到需要添加的数据,因为data数据中是一个一个对象,所以要放在一个对象中
let obj = {
id : data.length+1,
name : user.value,
password : pwd.value,
email : ema.value
}
// 将这个对象添加到数据中
data.push(obj)
// 点击提交按钮,重置input框
resRender()
// 重新渲染页面
render()
}
// 重置功能
res.onclick = () => {
// 点击重置按钮调用清空功能函数,重置input框
resRender()
}
// 封装删除功能
function del(id) { // 取到当前id
data.forEach((value, index) => {
// 判断原数组data中的id是不是和当前id一致
if(value.id === id) {
// 二次确认取消框
if(confirm('是否删除')) {
// 如果点击确认就删除原数组data中当前id的那一条数据
data.splice(index,1)
}
}
})
// 重新渲染页面
render()
}
// 实现本地存储功能
function hendleSetStorage(key, data) {
window.localStorage.setItem(key, JSON.stringify(data))
}
function hendleGetStorage(key) {
return JSON.parse(window.localStorage.getItem(key)) || []
}
// 编辑功能
function handleEditStudent() {
let edit = document.getElementsByClassName('edit')
let edit1 = [...edit]
edit1.forEach(v => {
v.addEventListener('click', function() {
let type = this.dataset.type;
let id = this.dataset.id;
let index = this.dataset.index;
data.forEach(item => {
if(+id === item.id) {
item.isEdit = type !== 'ok'
type === 'ok' && (item.name = document.getElementsByClassName('user-name-input')[index].value)
type === 'ok' && (item.password = document.getElementsByClassName('user-pwd-input')[index].value)
type === 'ok' && (item.email = document.getElementsByClassName('user-email-input')[index].value)
}
})
render()
})
})
}
以上就是我写的学生管理系统,希望对大家有所帮助