JavaScript使用数据驱动写一个学生管理系统

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

以上就是我写的学生管理系统,希望对大家有所帮助

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值