将一个项目改成无刷新分页,添加异步加载,实现信息记录的编辑与删除等功能
程序员文章站
2022-03-06 13:48:09
...
一. 先创建数据表并操作
//数据表操作
create table staffs (
sid int unsigned auto_increment not null primary key,
name varchar(20) not null comment '姓名',
gender enum('male','female') not null comment '性别',
email varchar(150) not null comment '邮箱',
birthday date not null comment '生日',
create_at timestamp not null default current_timestamp comment '创建日期',
update_at timestamp not null default current_timestamp on update current_timestamp comment '更新日期'
) engine = innodb auto_increment=1 collate = utf8mb4_unicode_ci;
// 创建 staffs 表 并插入数据
insert staffs (name,gender,salary,email,birthday)
values ('Lee','male',4500,'lee@php.cn','1983-02-10');
insert staffs set name='King', gender='male',salary=8899,
email='king@qq.com', birthday='1988-09-23';
insert staffs (name,gender, salary, email,birthday) values
('king','male',6500,'king@php.cn','1992-10-29'),
('amy','female',7800,'amy@163.com','1998-10-22'),
('betty','female',9800,'betty@qq.com','1953-10-19'),
('jack','male',12500,'jack@php.cn', '1977-10-24'),
('marry','female',15800,'marry@php.cn', '1990-01-08'),
('alice','female',8600,'alice@php.cn','1989-09-18'),
('admin','male',16600,'admin@php.cn','1989-09-18'),
('lisa','female',13500,'lisa@qq.com','1983-09-13'),
('peter','male',9600,'peter@163.com','1993-09-29'),
('linda','female',5600,'linda@163.com','1993-09-29');
二. 新建一个html文件用来渲染前端页面: staff.html
staff.html样式代码:
<!DOCTYPE html>
<html lang="zh-CN">
<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>员工管理系统</title>
<!-- 导入公共css样式代码 -->
<link rel="stylesheet" href="style.css" />
</head>
<body>
<table>
<caption>
员工管理系统
</caption>
<thead>
<tr>
<td>编号</td>
<td>姓名</td>
<td>性别</td>
<td>工资</td>
<td>邮箱</td>
<td>生日</td>
<td>入职时间</td>
<td>操作</td>
</tr>
</thead>
<!-- 数据渲染区域 -->
<tbody></tbody>
</table>
<!-- 分页渲染区域 -->
<p></p>
<!-- 模态框编辑区域 -->
<div class="modal">
<div class="modal-drop"></div>
<div class="modal-body">
<button class="close">关闭</button>
<form action="" name="editform">
<table>
<caption>
员工信息编辑
</caption>
<tbody>
<tr>
<td>姓名</td>
<td><input type="text" value="" name="name" id="name" /></td>
</tr>
<tr>
<td>性别</td>
<td>
<select name="gender" id="gender">
<option value="male" selected>男</option>
<option value="female">女</option>
</select>
</td>
</tr>
<tr>
<td>工资</td>
<td><input type="text" value="" name="salary" id="salary" /></td>
</tr>
<tr>
<td>邮箱</td>
<td><input type="text" value="" name="email" id="email" /></td>
</tr>
<tr>
<td>生日</td>
<td><input type="text" value="" name="birthday" id="birthday" /></td>
</tr>
<tr>
<td colspan="2"><button class="save">保存</button></td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
<!-- 模态框样式代码 -->
<style>
/* 模态框初始化隐藏 */
.modal {
display: none;
}
/* 遮盖层 */
.modal .modal-drop {
position: fixed;
background-color: rgb(0, 0, 0, 0.5);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.modal .modal-body {
position: fixed;
background-color: #fff;
padding: 1em;
overflow: hidden;
max-width: 25em;
max-height: 20em;
/* 水平垂直自动居中 */
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
/* 关闭按钮 */
.modal .modal-body .close {
position: absolute;
top: 1.1em;
right: 1.5em;
width: 3em;
height: 1.5em;
}
</style>
<!-- 导入外部js文件 -->
<script src="staff.js"></script>
</body>
</html>
导入默认公共style.css样式代码:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #555;
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
/*表格样式*/
table {
width: 90%;
border: 1px solid;
border-collapse: collapse;
text-align: center;
}
table caption {
font-size: 1.2rem;
margin: 10px;
}
table td,
table th {
border: 1px solid;
padding: 5px;
}
table tr:hover {
background-color: #eee;
}
table thead tr:only-of-type {
background-color: lightcyan;
}
table button {
width: 56px;
height: 26px;
}
table button:last-of-type {
color: red;
}
table button {
cursor: pointer;
margin: 0 3px;
}
/*分页条样式*/
body > p {
display: flex;
}
p > a {
text-decoration: none;
color: #555;
border: 1px solid #888;
padding: 5px 10px;
margin: 10px 2px;
}
.active {
background-color: seagreen;
color: white;
border: 1px solid seagreen;
}
再加上staff.js文件样式代码:
// 页面载入完成时默认渲染第一页数据
window.onload = function () {
select(1);
};
// 编辑和删除记录
document.querySelector("table:first-of-type tbody").addEventListener("click", (ev) => {
// 获取记录 id
const id = ev.target.parentNode.parentNode.querySelector("td").textContent * 1;
// 操作类型
switch (ev.target.textContent) {
case "编辑":
// 显示模态框
document.querySelector(".modal").style.display = "block";
// 点击关闭按钮,关闭模态框
document.querySelector(".modal .close").addEventListener("click", (eve) => {
document.querySelector(".modal").style.display = "none";
});
// 点击编辑按钮,关闭模态框
document.querySelector(".modal .save").addEventListener("click", (eve) => {
document.querySelector(".modal").style.display = "none";
});
// 点击模态框之外区域也关闭模态框
document.querySelector(".modal .modal-drop").addEventListener("click", (eve) => {
document.querySelector(".modal").style.display = "none";
});
// 获取数据
let name = ev.target.parentNode.parentNode.querySelector("td:nth-of-type(2)").textContent;
let gender = ev.target.parentNode.parentNode.querySelector("td:nth-of-type(3)").textContent;
let salary = ev.target.parentNode.parentNode.querySelector("td:nth-of-type(4)").textContent * 1;
let email = ev.target.parentNode.parentNode.querySelector("td:nth-of-type(5)").textContent;
let birthday = ev.target.parentNode.parentNode.querySelector("td:nth-of-type(6)").textContent;
// console.log(id, name, gender, salary, email, birthday);
// 渲染到模态框
document.getElementById("name").value = name;
document.getElementById("gender").value = gender;
document.getElementById("salary").value = salary;
document.getElementById("email").value = email;
document.getElementById("birthday").value = birthday;
// 编辑事件
document.querySelector(".modal .save").addEventListener("click", (eve) => {
// 禁止默认提交
eve.preventDefault();
// 获取模态框编辑数据
name = document.getElementById("name").value;
gender = document.getElementById("gender").value;
salary = document.getElementById("salary").value;
email = document.getElementById("email").value;
birthday = document.getElementById("birthday").value;
// console.log(id, name, gender, salary, email, birthday);
// 创建对象
let xhr = new XMLHttpRequest();
// 配置参数
xhr.open("post", "staff.php?action=update&id=" + id);
// 处理请求
xhr.onload = () => {
// console.log(xhr.response);
// 更新数据写回页面
ev.target.parentNode.parentNode.querySelector("td:nth-of-type(2)").textContent = name;
ev.target.parentNode.parentNode.querySelector("td:nth-of-type(3)").textContent = gender;
ev.target.parentNode.parentNode.querySelector("td:nth-of-type(4)").textContent = salary;
ev.target.parentNode.parentNode.querySelector("td:nth-of-type(5)").textContent = email;
ev.target.parentNode.parentNode.querySelector("td:nth-of-type(6)").textContent = birthday;
};
// 发送请求
xhr.send(new FormData(document.forms.namedItem("editform")));
});
break;
case "删除":
if (confirm("确认删除编号 " + id + " 记录?")) {
// 创建对象
let xhr = new XMLHttpRequest();
// 配置参数
xhr.open("get", "staff.php?action=delete&id=" + id);
// 处理请求
xhr.onload = () => {
// 删除节点
ev.target.parentNode.parentNode.remove();
};
// 发送请求
xhr.send(null);
}
break;
}
});
// 查
function select(page = 1) {
// 创建对象
const xhr = new XMLHttpRequest();
// 配置参数
xhr.open("get", "staff.php?action=select&page=" + page);
// 处理请求
xhr.onload = () => {
// json 格式数据解析为 js 对象
// console.log(xhr.response);
let res = JSON.parse(xhr.response);
let pages = res.pages;
let staffs = res.staffs;
// 渲染数据
document.querySelector("table:first-of-type tbody").innerHTML = get_datas(staffs);
// 渲染分页
document.querySelector("p:first-of-type").innerHTML = get_pages(page, pages);
};
// 发送请求
xhr.send(null);
}
// 无刷新分页
document.querySelector("p:first-of-type").addEventListener("click", (ev) => {
// 禁用默认跳转
ev.preventDefault();
// 点击当前激活页,无效点击
if (ev.target.classList.contains("active")) return;
// 去掉原激活样式
[...ev.currentTarget.children].forEach((ele) => ele.classList.remove("active"));
// 当前页添加激活样式
ev.target.classList.add("active");
let url = ev.target.href,
page;
// 获取页码
if (url.indexOf("?") !== -1) {
page = url.split("=")[1];
} else {
page = 1;
}
// 渲染点击页的数据
select(page);
});
// 渲染数据
function get_datas(datas) {
let str = "";
for (let i = 0; i < datas.length; i++) {
str += "<tr>";
str += "<td>" + datas[i]["id"] + "</td>";
str += "<td>" + datas[i]["name"] + "</td>";
str += "<td>" + datas[i]["gender"] + "</td>";
str += "<td>" + datas[i]["salary"] + "</td>";
str += "<td>" + datas[i]["email"] + "</td>";
str += "<td>" + datas[i]["birthday"] + "</td>";
str += "<td>" + datas[i]["create_at"] + "</td>";
str += "<td><button>编辑</button><button>删除</button></td>";
str += "</tr>";
}
return str;
}
// 分页数据
function get_pages(page = 1, pages) {
let paginate = "";
let active = "";
// 首页|上一页
if (page <= 1) page = 1;
if (page !== 1) {
paginate += '<a href="' + document.URL + '?p=1">首页</a>';
paginate += '<a href="' + document.URL + "?p=" + Math.max(1, page - 1) + '">上一页</a>';
}
// 高亮分页
for (i = 1; i <= pages; i++) {
active = "";
if (page == i) active = ' class="active"';
paginate += '<a href="' + document.URL + "?p=" + i + '"' + active + ">" + i + "</a>";
}
// 下一页|尾页
if (page >= pages) page = pages;
if (page !== pages) {
paginate += '<a href="' + document.URL + "?p=" + Math.min(page + 1, pages) + '">下一页</a>';
paginate += '<a href="' + document.URL + "?p=" + pages + '">尾页</a>';
}
return paginate;
}
最后由后端staff.php进行操作:
<?php
$config = [
'type' => 'mysql',
'host' => '127.0.0.1',
'dbname' => 'phpedu',
'port' => '3306',
'charset' => 'utf8mb4',
'username' => 'root',
'password' => 'root',
];
extract($config);
$dsn = sprintf('%s:host=%s;dbname=%s;port=%s;charset=%s', $type, $host, $dbname, $port, $charset);
try {
$pdo = new PDO($dsn, $username, $password);
// 设置结果集的返回类型
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// var_dump($pdo,'连接成功');
} catch (PDOException $e) {
die('连接失败:' . $e->getMessage());
}
// 每页显示记录数
$action = $_GET['action'] ?? 'select';
$page = $_GET['page'] ?? 1;
switch ($action) {
// 增
case 'add':
break;
// 删
case 'delete':
die(del_data($pdo, $_GET['id'] ?? 0));
break;
// 改
case 'update':
$id = $_GET['id'] ?? 0;
$name = $_POST['name'];
$gender = $_POST['gender'];
$salary = $_POST['salary'];
$email = $_POST['email'];
$birthday = $_POST['birthday'];
die(update_data($pdo, $id, $name, $gender, $salary, $email, $birthday));
break;
// 查
case 'select':
die(get_datas($pdo, $page));
}
// 更新记录
function update_data($pdo, $id, $name, $gender, $salary, $email, $birthday)
{
if ($id) {
$sql = "UPDATE staffs SET name = :name, gender = :gender, salary = :salary, email = :email, birthday = :birthday WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':gender', $gender, PDO::PARAM_STR);
$stmt->bindParam(':salary', $salary, PDO::PARAM_INT);
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->bindParam(':birthday', $birthday, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0) {
return '更新成功!';
}
}
return '更新错误!';
}
// 删除记录
function del_data($pdo, $id = 0)
{
if ($id) {
$sql = "DELETE FROM staffs WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
return '删除成功!';
}
}
return '删除错误!';
}
// 数据总页数
function get_pages($pdo, $page = 1, $num = 5)
{
// 总页数
$num = 5;
$offset = ($page - 1) * $num;
$sql = "SELECT CEIL(COUNT(1)/{$num}) total FROM staffs";
$pages = $pdo->query($sql)->fetch()['total'];
return $pages;
}
// 每页显示数
function get_datas($pdo, $page = 1, $num = 5)
{
// 获取总页数
$pages = get_pages($pdo);
// 每页显示的数据
$offset = ($page - 1) * $num;
$sql = "SELECT * FROM `staffs` LIMIT {$offset}, {$num}";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$staffs = $stmt->fetchAll();
$staffs = $pdo->query($sql)->fetchAll();
return json_encode(['pages' => $pages, 'staffs' => $staffs]);
}
效果预览:
使用Ajax无刷新分页效果预览:
对编号14的员工数据进行编辑,把姓名改为中文且工资过万效果预览:
编辑成功效果预览:
删除编号13的员工数据效果预览:
删除成功后效果预览:
上一篇: CSS盒模型常用属性,单位,选择器
下一篇: jquery如何让a标签不可用