本系统是基于BootStrap、JavaScript和LocalStorage技术实现对数据信息的展示、本地存储、查询、增加、删除。

信息管理系统:

效果图:

BootStrap页面布局:

本系统使用了BootStrap前端框架实现了页面数据的布局展示,这里简单介绍一下BootStrap和具体使用。

BootStrap介绍:

1、前端框架,HTML、CSS、JavaScript工具集,让web开发更简单便捷。

2、拥有响应式设计,12列格网,自定义JQuery插件,完整类库。

3、适合后端程序员针对前端页面的快速开发。

BootStrap的使用:

下载:

下载网址:Bootstrap · The most popular HTML, CSS, and JS library in the world.

这里建议使用老版本,新版本使用起来可能不稳定,老版本更加可靠一点。

引入:

首先在head头标签中引入下载的BootStrap的CSS类库。

<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">

然后引入Jquery插件和JS插件,BootStrap是基于Jquery的,所以在引入BootStrap的JS插件之前先引入Jquery插件(本篇文章代码中没有引入自己本地的Jquery文件,引入的Staticfile CDN 上的库)。

<script src="https://cdn.staticfile.net/jquery/2.1.1/jquery.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
使用:

本系统主要用到了BootStrap的container容器布局页面元素,BootStrap表单实现数据录入,BootStrap按钮进行数据操作,BootStrap表格实现数据展示。

BootStrap的具体使用可以参考BootStrap教程|菜鸟教程:

Bootstrap 教程 | 菜鸟教程

JavaScript操纵元素数据:

数据录入:

通过Document对象根据CSS选择器和ID选择器获取Form表单输入框DOM元素,使用const声明常量存储DOM对象。

const nameInput = document.querySelector('.form-group #name');
const ageInput = document.querySelector('.form-group #age');
const genderInput = document.querySelector('.form-group #gender');
const salaryInput = document.querySelector('.form-group #salary');
const workCityInput = document.querySelector('.form-group #workCity');

通过value属性获取DOM节点数据(注意这里的学号为系统生成,根据学员信息中最后一个学员也就是最新录入的学员的学号+1作为新学员的学号):

疑问:为什么不用学员信息.length+1作为新学员的学号呢?

答:假设当前学员信息中有001学员和002学员,我们先删除001学员,那么学员信息中只剩下002学员,然后我们录入新的学员信息,新学员的学号=002(学员信息.length+1即1+1),这样当前学员信息中有两个学号为002的学员信息,这样明显是不对的,所以这里采用学员信息中最后一个学员学号+1作为新学员的学号。

let number = '001';
    // JS短路运算
	if (studentInfo && studentInfo.length) {
		// 新增学员信息的学号为 数组中最后一个学员学号+1
		number = parseInt(studentInfo[studentInfo.length - 1].number) + 1;
	}
const numberValue = String(number).padStart(3, '0');
const nameValue = nameInput.value;
const ageValue = ageInput.value;
const genderValue = genderInput.value;
const salaryValue = salaryInput.value;
const workCityValue = workCityInput.value;
const inputTime = getNowTime();

数据校验:

 录入数据提交时进行数据校验(例如录入数据不能为空,姓名只能是英文或中文,年龄在合法范围,薪资不允许为负),这里使用了alert弹框向用户展示警告信息。

// 中文字符
const chineseCharsRegex = /^[\u4e00-\u9fa5]{0,}$/;
// 英文字符
const englishCharsRegex = /^[A-Za-z]+$/;

if (!nameValue) {
    alert('姓名不允许为空!');
	return;
} else if (!(nameValue.match(chineseCharsRegex) || nameValue.match(englishCharsRegex))) {
	alert('姓名数据不合法!');
	return;
} else if (!ageValue) {
	alert('年龄不允许为空!');
	return;
} else if (ageValue > 120 || ageValue < 1) {
	alert('年龄超出合法范围(1-120)');
	return;
} else if (!salaryValue) {
	alert('薪资不允许为空!');
	return;
} else if (salaryValue < 0) {
	alert('薪资不允许为负!');
	return;
}

LocalStorage本地存储:

将学员信息数据封装成studentData对象后存入到数组中,将学员信息数组转换成JSON字符串存储到本地,在存储完录入数据之后需要重置表单重新查询数据

疑问:为什么不将studentData对象直接存储到localStroage中呢?

回答:因为若不转换成JSON字符串直接存储的话存储的是obj字符串,LocalStorage只能存储简单类型数据,像obj对象和array数组需要转换成JSON以字符串的形式存储到本地中

const studentData = {
	'number': numberValue,
	'name': nameValue,
	'age': ageValue,
	'gender': genderValue,
	'salary': salaryValue,
	'workCity': workCityValue,
	'inputTime': inputTime
}
studentInfo.push(studentData);

localStorage.setItem('studentInfo', JSON.stringify(studentInfo));

// 重置表单
document.querySelector('form').reset();
// 重新查询
selectData();

获取数据:

 获取localStorage本地存储的JSON数据,通过JSON.parse(json字符串)将JSON数据转换回JS数据后进行展示操作。

// 先获取localStorage本地存储的学生信息数据
const localStudentInfo = JSON.parse(localStorage.getItem('studentInfo'));
studentInfo = localStudentInfo ? localStudentInfo : [];

创建DOM节点以及对节点内容添加数据展示:

 在渲染数据之前先清空tbody中的所有数据避免数据重复渲染,后通过循环给每个学员添加<td>数据信息展示,最后每个学员信息后添加修改和删除按钮,两个按钮需要添加自定义属性记录该学员存在于数组的位置下标,方便后面修改和删除时根据数组下标位置去定位学员信息

const tbody = document.querySelector('.table tbody');
// 清空之前的tbody数据 避免重复渲染
tbody.innerHTML = '';
for (let i = 0; i < studentInfo.length; i++) {
	const tr = document.createElement('tr');
	tr.innerHTML =
		`<td>${studentInfo[i].number}</td>
		<td>${studentInfo[i].name}</td>
		<td>${studentInfo[i].age}</td>
		<td>${studentInfo[i].gender}</td>
		<td>${studentInfo[i].salary}</td>
		<td>${studentInfo[i].workCity}</td>
		<td>${studentInfo[i].inputTime}</td>
		<td><button type='button' data-index = ${i} id='update' class='btn btn-primary btn-sm' style="margin-right: 10px;">修改</button>
		<button type='button' data-index = ${i} id='delete' class='btn btn-warning btn-sm'>删除</button></td>`;
	tbody.appendChild(tr);
};

数据删除:

 事件监听时通过事件委托为父元素table注册事件,这样不需要再为每个删除按钮添加事件监听,在table被点击时判断是否是table中的删除按钮被点击,后通过按钮的自定义属性获取当前需要删除的数据所处数组下标位置进行定位删除。

在localStorage本地存储中通过setItem方法通过key将新数据覆盖掉旧数据实现数据的修改操作。

// 事件委托(给父元素table注册事件 不需要再为每个按钮添加事件监听) 
// 删除(通过按钮的自定义属性获取数组下标进行删除)
document.querySelector('.table').addEventListener('click', function(e) {
	const target = e.target;
	const indexNumber = target.dataset.index;
	if (target.id == 'delete') {
		const dropStudentName = studentInfo[indexNumber].name;
		if (confirm(`确定要删除${dropStudentName}这条数据吗?`)) {
			studentInfo.splice(indexNumber, 1);
			localStorage.setItem('studentInfo', JSON.stringify(studentInfo));
			selectData();
		}
	} else if (target.id == 'update') {
		// 页面跳转
		location.href = 'http://www.baidu.com';
	}
});

删库跑路: 

终于到期待已久的删库跑路了,in terms of salary, this job is not very attractive,不如删库跑路喽!

这里通过localStorage.removeItem(key)进行对key针对性删除,也可以使用localStorage.clear() 清空所有的存储项。

// 清空所有数据
document.querySelector('table #clearAllData').addEventListener('click', function() {
    // 弹出对话框提示是否清空
    let result = confirm('确定清空所有数据?');
    if (result) {
	    localStorage.removeItem('studentInfo');
	    selectData();
    }
});

整体代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>学员信息管理系统</title>
		<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
		<script src="https://cdn.staticfile.net/jquery/2.1.1/jquery.min.js"></script>
		<script src="bootstrap/js/bootstrap.min.js"></script>
		<style>
			.textTitle {
				font-size: 25px;
				font-weight: bold;
				margin-top: 20px;
				margin-bottom: 20px;
			}

			.table th {
				text-align: center;
				background-color: #7fc8fd;
			}
		</style>
	</head>
	<body>
		<div class="container" style="text-align: center;">
			<div class="textTitle">新增学员</div>
			<!-- form表单的autocomplete属性是历史录入数据是否打开展示, off关闭 -->
			<form class="form-inline" role="form" style="text-align: center;" autocomplete="off">
				<div class="form-group">
					<label for="name">姓名: </label>
					<input type="text" class="form-control" id="name" maxlength="7" style="width: 120px;">
				</div>
				<div class="form-group" style="padding-left: 20px;">
					<label for="age">年龄: </label>
					<input type="number" class="form-control" id="age" style="width: 100px;">
				</div>

				<div class="form-group" style="padding-left: 20px;">
					<label for="gender">性别: </label>
					<select id="gender" class="form-control">
						<option>男</option>
						<option>女</option>
					</select>
				</div>

				<div class="form-group" style="padding-left: 20px;">
					<label for="salary">薪资: </label>
					<input type="number" class="form-control" id="salary" style="width: 100px;">
				</div>

				<div class="form-group" style="padding-left: 20px;">
					<label for="workCity">就业城市: </label>
					<select id="workCity" class="form-control">
						<option>北京</option>
						<option>济南</option>
						<option>重庆</option>
						<option>杭州</option>
					</select>
				</div>

				<button type="button" id="submit" class="btn btn-primary" style="margin-left: 50px;">录入</button>

			</form>

			<div class="textTitle" style="margin-top: 50px;">就业榜</div>
			<table class="table table-bordered table-hover table-condensed">
				<thead>
					<tr>
						<td colspan="8" style="text-align: right; padding-right: 20px;">
							<span id="countDataInfo" style="padding-right: 10px; font-weight: bold;"></span>
							<button id="clearAllData" type="button" class="btn btn-danger btn-xs">删库跑路</button>
						</td>
					</tr>
					<tr>
						<th>学号</th>
						<th>姓名</th>
						<th>年龄</th>
						<th>性别</th>
						<th>薪资</th>
						<th>就业城市</th>
						<th>录入时间</th>
						<th>操作</th>
					</tr>
				</thead>
				<tbody>
				</tbody>
			</table>
		</div>

		<script>
			let studentInfo = [];

			const nameInput = document.querySelector('.form-group #name');
			const ageInput = document.querySelector('.form-group #age');
			const genderInput = document.querySelector('.form-group #gender');
			const salaryInput = document.querySelector('.form-group #salary');
			const workCityInput = document.querySelector('.form-group #workCity');

			// 特殊字符
			const specialCharsRegex = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+/;
			// 数字字符
			const numberCharsRegex = /^[0-9]*$/;
			// 中文字符
			const chineseCharsRegex = /^[\u4e00-\u9fa5]{0,}$/;
			// 英文字符
			const englishCharsRegex = /^[A-Za-z]+$/;

			// 优先渲染数据
			selectData();

			function selectData() {
				// 先获取localStorage本地存储的学生信息数据
				const localStudentInfo = JSON.parse(localStorage.getItem('studentInfo'));
				studentInfo = localStudentInfo ? localStudentInfo : [];

				// 页面展示数据个数
				document.querySelector('table #countDataInfo').innerHTML = `共有${studentInfo.length}条数据`


				const tbody = document.querySelector('.table tbody');
				// 清空之前的tbody数据 避免重复渲染
				tbody.innerHTML = '';
				for (let i = 0; i < studentInfo.length; i++) {
					const tr = document.createElement('tr');
					tr.innerHTML =
						`<td>${studentInfo[i].number}</td>
						<td>${studentInfo[i].name}</td>
						<td>${studentInfo[i].age}</td>
						<td>${studentInfo[i].gender}</td>
						<td>${studentInfo[i].salary}</td>
						<td>${studentInfo[i].workCity}</td>
						<td>${studentInfo[i].inputTime}</td>
						<td><button type='button' data-index = ${i} id='update' class='btn btn-primary btn-sm' style="margin-right: 10px;">修改</button>
						<button type='button' data-index = ${i} id='delete' class='btn btn-warning btn-sm'>删除</button></td>`;
					tbody.appendChild(tr);
				}
			};

			document.querySelector('.container #submit').addEventListener('click', function() {
				submit();
			});

			// 事件委托(给父元素table注册事件 不需要再为每个按钮添加事件监听) 
			// 删除(通过按钮的自定义属性获取数组下标进行删除)
			document.querySelector('.table').addEventListener('click', function(e) {
				const target = e.target;
				const indexNumber = target.dataset.index;
				if (target.id == 'delete') {
					const dropStudentName = studentInfo[indexNumber].name;
					if (confirm(`确定要删除${dropStudentName}这条数据吗?`)) {
						studentInfo.splice(indexNumber, 1);
						localStorage.setItem('studentInfo', JSON.stringify(studentInfo));
						selectData();
					}
				} else if (target.id == 'update') {
					// 页面跳转
					location.href = 'http://www.baidu.com';
				}
			});

			// 清空所有数据
			document.querySelector('table #clearAllData').addEventListener('click', function() {
				// 弹出对话框提示是否清空
				let result = confirm('确定清空所有数据?');
				if (result) {
					localStorage.removeItem('studentInfo');
					selectData();
				}
			});



			function submit() {
				let number = '001';
				// JS短路运算
				if (studentInfo && studentInfo.length) {
					// 新增学员信息的学号为 数组中最后一个学员学号+1
					number = parseInt(studentInfo[studentInfo.length - 1].number) + 1;
				}
				const numberValue = String(number).padStart(3, '0');
				const nameValue = nameInput.value;
				const ageValue = ageInput.value;
				const genderValue = genderInput.value;
				const salaryValue = salaryInput.value;
				const workCityValue = workCityInput.value;
				const inputTime = getNowTime();

				if (!nameValue) {
					alert('姓名不允许为空!');
					return;
				} else if (!(nameValue.match(chineseCharsRegex) || nameValue.match(englishCharsRegex))) {
					alert('姓名数据不合法!');
					return;
				} else if (!ageValue) {
					alert('年龄不允许为空!');
					return;
				} else if (ageValue > 120 || ageValue < 1) {
					alert('年龄超出合法范围(1-120)');
					return;
				} else if (!salaryValue) {
					alert('薪资不允许为空!');
					return;
				} else if (salaryValue < 0) {
					alert('薪资不允许为负!');
					return;
				}

				const studentData = {
					'number': numberValue,
					'name': nameValue,
					'age': ageValue,
					'gender': genderValue,
					'salary': salaryValue,
					'workCity': workCityValue,
					'inputTime': inputTime
				}
				studentInfo.push(studentData);

				localStorage.setItem('studentInfo', JSON.stringify(studentInfo));

				// 重置表单
				document.querySelector('form').reset();

				selectData();
			}

			function getNowTime() {
				const nowDate = new Date();
				const nowYear = String(nowDate.getFullYear());
				const nowMonth = String(nowDate.getMonth() + 1).padStart(2, '0');
				const nowDay = String(nowDate.getDate()).padStart(2, '0');
				const nowHour = String(nowDate.getHours()).padStart(2, '0');
				const nowMinute = String(nowDate.getMinutes()).padStart(2, '0');
				const nowSecond = String(nowDate.getSeconds()).padStart(2, '0');
				const nowDataTypeTransformString = `${nowYear}/${nowMonth}/${nowDay} ${nowHour}:${nowMinute}:${nowSecond}`;
				return nowDataTypeTransformString;
			}
		</script>
	</body>
</html>

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐