Blogger Information
Blog 70
fans 1
comment 0
visits 52949
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
静态单页-项目数据-无刷新分页-增删改...
葡萄枝子
Original
757 people have browsed it

静态单页-项目数据-无刷新分页-增删改…

  1. 将项目改造成无刷新分页,前端用Ajax实现数据异步加载
  2. 实现记录的编辑与删除功能,想一下如何优雅的实现它

1. 往 staffs 表添加默认数据

  1. insert staffs (name,gender, salary, email,birthday) values
  2. ('king','male',6500,'king@php.cn','1992-10-29'),
  3. ('amy','female',7800,'amy@163.com','1998-10-22'),
  4. ('betty','female',9800,'betty@qq.com','1953-10-19'),
  5. ('jack','male',12500,'jack@php.cn', '1977-10-24'),
  6. ('marry','female',15800,'marry@php.cn', '1990-01-08'),
  7. ('alice','female',8600,'alice@php.cn','1989-09-18'),
  8. ('admin','male',16600,'admin@php.cn','1989-09-18'),
  9. ('lisa','female',13500,'lisa@qq.com','1983-09-13'),
  10. ('peter','male',9600,'peter@163.com','1993-09-29'),
  11. ('linda','female',5600,'linda@163.com','1993-09-29');

2. 新建前端渲染文件 0226.html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>员工管理系统</title>
  8. <link rel="stylesheet" href="style.css">
  9. </head>
  10. <body>
  11. <table>
  12. <caption>员工管理系统</caption>
  13. <thead>
  14. <tr>
  15. <td>编号</td>
  16. <td>姓名</td>
  17. <td>性别</td>
  18. <td>工资</td>
  19. <td>邮箱</td>
  20. <td>生日</td>
  21. <td>入职时间</td>
  22. <td>操作</td>
  23. </tr>
  24. </thead>
  25. <!-- 数据渲染区 -->
  26. <tbody></tbody>
  27. </table>
  28. <!-- 分页渲染区 -->
  29. <p></p>
  30. <!-- 模态框编辑区 -->
  31. <div class="modal">
  32. <div class="modal-drop"></div>
  33. <div class="modal-body">
  34. <button class="close">关闭</button>
  35. <form action="" name="editform">
  36. <table>
  37. <caption>员工信息编辑</caption>
  38. <tbody>
  39. <tr>
  40. <td>姓名</td>
  41. <td><input type="text" value="" name="name" id="name"></td>
  42. </tr>
  43. <tr>
  44. <td>性别</td>
  45. <td>
  46. <select name="gender" id="gender">
  47. <option value="male" selected></option>
  48. <option value="female"></option>
  49. </select>
  50. </td>
  51. </tr>
  52. <tr>
  53. <td>工资</td>
  54. <td><input type="text" value="" name="salary" id="salary"></td>
  55. </tr>
  56. <tr>
  57. <td>邮箱</td>
  58. <td><input type="text" value="" name="email" id="email"></td>
  59. </tr>
  60. <tr>
  61. <td>生日</td>
  62. <td><input type="text" value="" name="birthday" id="birthday"></td>
  63. </tr>
  64. <tr>
  65. <td colspan="2"><button class="save">保存</button></td>
  66. </tr>
  67. </tbody>
  68. </table>
  69. </form>
  70. </div>
  71. </div>
  72. <!-- 模态框样式 -->
  73. <style>
  74. /* 模态框初始化隐藏 */
  75. .modal {
  76. display: none;
  77. }
  78. /* 遮罩层 */
  79. .modal .modal-drop {
  80. position: fixed;
  81. background-color: rgb(0, 0, 0, .5);
  82. top: 0;
  83. left: 0;
  84. right: 0;
  85. bottom: 0;
  86. }
  87. .modal .modal-body {
  88. position: fixed;
  89. background-color: #fff;
  90. padding: 1em;
  91. overflow: hidden;
  92. max-width: 25em;
  93. max-height: 20em;
  94. /* 水平垂直自动居中 */
  95. top: 0;
  96. left: 0;
  97. right: 0;
  98. bottom: 0;
  99. margin: auto;
  100. }
  101. /* 关闭按钮 */
  102. .modal .modal-body .close {
  103. position: absolute;
  104. top: 1.1em;
  105. right: 1.5em;
  106. width: 3em;
  107. height: 1.5em;
  108. }
  109. </style>
  110. <!-- 引入js文件 -->
  111. <script src="0226.js"></script>
  112. </body>
  113. </html>

3. 引入的 style.css 是默认的

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. color: #555;
  6. }
  7. body {
  8. display: flex;
  9. flex-direction: column;
  10. align-items: center;
  11. }
  12. /*表格样式*/
  13. table {
  14. width: 90%;
  15. border: 1px solid;
  16. border-collapse: collapse;
  17. text-align: center;
  18. }
  19. table caption {
  20. font-size: 1.2rem;
  21. margin: 10px;
  22. }
  23. table td,
  24. table th {
  25. border: 1px solid;
  26. padding: 5px;
  27. }
  28. table tr:hover {
  29. background-color: #eee;
  30. }
  31. table thead tr:only-of-type {
  32. background-color: lightcyan;
  33. }
  34. table button {
  35. width: 56px;
  36. height: 26px;
  37. }
  38. table button:last-of-type {
  39. color: red;
  40. }
  41. table button {
  42. cursor: pointer;
  43. margin: 0 3px;
  44. }
  45. /*分页条样式*/
  46. body > p {
  47. display: flex;
  48. }
  49. p > a {
  50. text-decoration: none;
  51. color: #555;
  52. border: 1px solid #888;
  53. padding: 5px 10px;
  54. margin: 10px 2px;
  55. }
  56. .active {
  57. background-color: seagreen;
  58. color: white;
  59. border: 1px solid seagreen;
  60. }

4. 引入的 0226.js 文件代码

  1. // 页面载入完成时默认渲染第一页数据
  2. window.onload = function () {
  3. select(1);
  4. };
  5. // 增
  6. // ...
  7. // 编辑和删除记录
  8. document.querySelector('table:first-of-type tbody').addEventListener('click', ev => {
  9. // 获取记录 id
  10. const id = ev.target.parentNode.parentNode.querySelector('td').textContent * 1;
  11. // 操作类型
  12. switch (ev.target.textContent) {
  13. case '编辑':
  14. // 显示模态框
  15. document.querySelector('.modal').style.display = 'block';
  16. // 点击关闭按钮,关闭模态框
  17. document.querySelector('.modal .close').addEventListener('click', (eve) => {
  18. document.querySelector('.modal').style.display = 'none';
  19. });
  20. // 点击编辑按钮,关闭模态框
  21. document.querySelector('.modal .save').addEventListener('click', (eve) => {
  22. document.querySelector('.modal').style.display = 'none';
  23. });
  24. // 点击模态框之外区域也关闭模态框
  25. document.querySelector('.modal .modal-drop').addEventListener('click', (eve) => {
  26. document.querySelector('.modal').style.display = 'none';
  27. });
  28. // 获取数据
  29. let name = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(2)').textContent;
  30. let gender = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(3)').textContent;
  31. let salary = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(4)').textContent * 1;
  32. let email = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(5)').textContent;
  33. let birthday = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(6)').textContent;
  34. // console.log(id, name, gender, salary, email, birthday);
  35. // 渲染到模态框
  36. document.getElementById('name').value = name;
  37. document.getElementById('gender').value = gender;
  38. document.getElementById('salary').value = salary;
  39. document.getElementById('email').value = email;
  40. document.getElementById('birthday').value = birthday;
  41. // 编辑事件
  42. document.querySelector('.modal .save').addEventListener('click', (eve) => {
  43. // 禁止默认提交
  44. eve.preventDefault();
  45. // 获取模态框编辑数据
  46. name = document.getElementById('name').value;
  47. gender = document.getElementById('gender').value;
  48. salary = document.getElementById('salary').value;
  49. email = document.getElementById('email').value;
  50. birthday = document.getElementById('birthday').value;
  51. // console.log(id, name, gender, salary, email, birthday);
  52. // 创建对象
  53. let xhr = new XMLHttpRequest();
  54. // 配置参数
  55. xhr.open('post', 'handle.php?action=update&id=' + id);
  56. // 处理请求
  57. xhr.onload = () => {
  58. // console.log(xhr.response);
  59. // 更新数据写回页面
  60. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(2)').textContent = name;
  61. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(3)').textContent = gender;
  62. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(4)').textContent = salary;
  63. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(5)').textContent = email;
  64. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(6)').textContent = birthday;
  65. };
  66. // 发送请求
  67. xhr.send(new FormData(document.forms.namedItem('editform')));
  68. });
  69. break;
  70. case '删除':
  71. if (confirm('确认删除编号 ' + id + ' 记录?')) {
  72. // 创建对象
  73. let xhr = new XMLHttpRequest();
  74. // 配置参数
  75. xhr.open('get', 'handle.php?action=delete&id=' + id);
  76. // 处理请求
  77. xhr.onload = () => {
  78. // 删除节点
  79. ev.target.parentNode.parentNode.remove();
  80. };
  81. // 发送请求
  82. xhr.send(null);
  83. }
  84. break
  85. }
  86. });
  87. // 查
  88. function select(page = 1) {
  89. // 创建对象
  90. const xhr = new XMLHttpRequest();
  91. // 配置参数
  92. xhr.open('get', 'handle.php?action=select&page=' + page);
  93. // 处理请求
  94. xhr.onload = () => {
  95. // json 格式数据解析为 js 对象
  96. // console.log(xhr.response);
  97. let res = JSON.parse(xhr.response);
  98. let pages = res.pages;
  99. let staffs = res.staffs;
  100. // 渲染数据
  101. document.querySelector('table:first-of-type tbody').innerHTML = get_datas(staffs);
  102. // 渲染分页
  103. document.querySelector('p:first-of-type').innerHTML = get_pages(page, pages);
  104. };
  105. // 发送请求
  106. xhr.send(null);
  107. }
  108. // 无刷新分页
  109. document.querySelector('p:first-of-type').addEventListener('click', ev => {
  110. // 禁用默认跳转
  111. ev.preventDefault();
  112. // 点击当前激活页,无效点击
  113. if (ev.target.classList.contains('active')) return;
  114. // 去掉原激活样式
  115. [...ev.currentTarget.children].forEach(ele => ele.classList.remove('active'));
  116. // 当前页添加激活样式
  117. ev.target.classList.add('active');
  118. let url = ev.target.href, page;
  119. // 获取页码
  120. if (url.indexOf("?") !== -1) {
  121. page = url.split("=")[1];
  122. } else {
  123. page = 1;
  124. }
  125. // 渲染点击页的数据
  126. select(page);
  127. });
  128. // 渲染数据
  129. function get_datas(datas) {
  130. let str = '';
  131. for (let i = 0; i < datas.length; i++) {
  132. str += '<tr>';
  133. str += '<td>' + datas[i]['id'] + '</td>';
  134. str += '<td>' + datas[i]['name'] + '</td>';
  135. str += '<td>' + datas[i]['gender'] + '</td>';
  136. str += '<td>' + datas[i]['salary'] + '</td>';
  137. str += '<td>' + datas[i]['email'] + '</td>';
  138. str += '<td>' + datas[i]['birthday'] + '</td>';
  139. str += '<td>' + datas[i]['create_at'] + '</td>';
  140. str += '<td><button>编辑</button><button>删除</button></td>';
  141. str += '</tr>';
  142. }
  143. return str;
  144. }
  145. // 分页数据
  146. function get_pages(page = 1, pages) {
  147. let paginate = '';
  148. let active = '';
  149. // 首页|上一页
  150. if (page <= 1) page = 1;
  151. if (page !== 1) {
  152. paginate += '<a href="' + document.URL + '?p=1">首页</a>';
  153. paginate += '<a href="' + document.URL + '?p=' + Math.max(1, page - 1) + '">上一页</a>';
  154. }
  155. // 高亮分页
  156. for (i = 1; i <= pages; i++) {
  157. active = '';
  158. if (page == i) active = ' class="active"';
  159. paginate += '<a href="' + document.URL + '?p=' + i + '"' + active + '>' + i + '</a>';
  160. }
  161. // 下一页|尾页
  162. if (page >= pages) page = pages;
  163. if (page !== pages) {
  164. paginate += '<a href="' + document.URL + '?p=' + Math.min(page + 1, pages) + '">下一页</a>';
  165. paginate += '<a href="' + document.URL + '?p=' + pages + '">尾页</a>';
  166. }
  167. return paginate;
  168. }

5. 后端处理 handle.php

  1. <?php
  2. $config = [
  3. 'type' => 'mysql',
  4. 'host' => '127.0.0.1',
  5. 'dbname' => 'phpedu',
  6. 'port' => '3306',
  7. 'charset' => 'utf8mb4',
  8. 'username' => 'root',
  9. 'password' => 'root',
  10. ];
  11. extract($config);
  12. $dsn = sprintf('%s:host=%s;dbname=%s;port=%s;charset=%s', $type, $host, $dbname, $port, $charset);
  13. try {
  14. $pdo = new PDO($dsn, $username, $password);
  15. // 设置结果集的返回类型
  16. $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  17. // var_dump($pdo,'连接成功');
  18. } catch (PDOException $e) {
  19. die('连接失败:' . $e->getMessage());
  20. }
  21. // 每页显示记录数
  22. $action = $_GET['action'] ?? 'select';
  23. $page = $_GET['page'] ?? 1;
  24. switch ($action) {
  25. // 增
  26. case 'add':
  27. // ...
  28. break;
  29. // 删
  30. case 'delete':
  31. die(del_data($pdo, $_GET['id'] ?? 0));
  32. break;
  33. // 改
  34. case 'update':
  35. $id = $_GET['id'] ?? 0;
  36. $name = $_POST['name'];
  37. $gender = $_POST['gender'];
  38. $salary = $_POST['salary'];
  39. $email = $_POST['email'];
  40. $birthday = $_POST['birthday'];
  41. die(update_data($pdo, $id, $name, $gender, $salary, $email, $birthday));
  42. break;
  43. // 查
  44. case 'select':
  45. die(get_datas($pdo, $page));
  46. }
  47. // 更新记录
  48. function update_data($pdo, $id, $name, $gender, $salary, $email, $birthday)
  49. {
  50. if ($id) {
  51. $sql = "UPDATE staffs SET name = :name, gender = :gender, salary = :salary, email = :email, birthday = :birthday WHERE id = :id";
  52. $stmt = $pdo->prepare($sql);
  53. $stmt->bindParam(':id', $id, PDO::PARAM_INT);
  54. $stmt->bindParam(':name', $name, PDO::PARAM_STR);
  55. $stmt->bindParam(':gender', $gender, PDO::PARAM_STR);
  56. $stmt->bindParam(':salary', $salary, PDO::PARAM_INT);
  57. $stmt->bindParam(':email', $email, PDO::PARAM_STR);
  58. $stmt->bindParam(':birthday', $birthday, PDO::PARAM_STR);
  59. $stmt->execute();
  60. if ($stmt->rowCount() > 0) {
  61. return '更新成功!';
  62. }
  63. }
  64. return '更新错误!';
  65. }
  66. // 删除记录
  67. function del_data($pdo, $id = 0)
  68. {
  69. if ($id) {
  70. $sql = "DELETE FROM staffs WHERE id = :id";
  71. $stmt = $pdo->prepare($sql);
  72. $stmt->bindParam(':id', $id, PDO::PARAM_INT);
  73. $stmt->execute();
  74. if ($stmt->rowCount() > 0) {
  75. return '删除成功!';
  76. }
  77. }
  78. return '删除错误!';
  79. }
  80. // 数据总页数
  81. function get_pages($pdo, $page = 1, $num = 5)
  82. {
  83. // 总页数
  84. $num = 5;
  85. $offset = ($page - 1) * $num;
  86. $sql = "SELECT CEIL(COUNT(1)/{$num}) total FROM staffs";
  87. $pages = $pdo->query($sql)->fetch()['total'];
  88. return $pages;
  89. }
  90. // 每页显示数
  91. function get_datas($pdo, $page = 1, $num = 5)
  92. {
  93. // 获取总页数
  94. $pages = get_pages($pdo);
  95. // 每页显示的数据
  96. $offset = ($page - 1) * $num;
  97. $sql = "SELECT * FROM `staffs` LIMIT {$offset}, {$num}";
  98. $stmt = $pdo->prepare($sql);
  99. $stmt->execute();
  100. $staffs = $stmt->fetchAll();
  101. $staffs = $pdo->query($sql)->fetchAll();
  102. return json_encode(['pages' => $pages, 'staffs' => $staffs]);
  103. }

运行 0226.html 附图

效果图

  • 点击第 3 页,ajax 翻页

ajax翻页

  • 点击编号是 14 倒数第2个记录,模态框编辑

模态框编辑

  • 修改姓名 peter 为 test 性别为女,保存,信息无刷新回滚页面

编辑信息

  • 删除刚修改的姓名为 test 的记录,单击确认

删除记录

  • 编号为 14 的记录,已无刷新删除

无刷新删除

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:完成的相当棒,已经有一个项目的雏形了
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments