# :-: 一、分页原理
### 1、基本术语
* 记录索引: 记录在表中的位置,从0开始(与主键无关)
* 偏移量: 每页显示的起始位置
* 显示数量: 每页默认的显示数量
```[mysql]
# 为了测试方便,我们先增加一些数据
INSERT INTO `user` VALUES (2, '13011113333', '洪七公', 'e10adc3949ba59abbe56e057f20f883e', 74, 1, 1, 1554282409);
INSERT INTO `user` VALUES (3, '18722223333', '黄蓉', 'e10adc3949ba59abbe56e057f20f883e', 17, 2, 1, 1554282409);
INSERT INTO `user` VALUES (4, '18722224444', '郭靖', 'e10adc3949ba59abbe56e057f20f883e', 23, 1, 1, 1554282409);
INSERT INTO `user` VALUES (5, '18722225555', '黄药师', 'e10adc3949ba59abbe56e057f20f883e', 58, 1, 1, 1554282409);
INSERT INTO `user` VALUES (6, '18722226666', '周伯通', 'e10adc3949ba59abbe56e057f20f883e', 53, 1, 1, 1554282409);
INSERT INTO `user` VALUES (7, '18722227777', '杨过', 'e10adc3949ba59abbe56e057f20f883e', 1, 1, 1, 1554282409);
INSERT INTO `user` VALUES (8, '18722228888', '杨康', 'e10adc3949ba59abbe56e057f20f883e', 22, 1, 1, 1554282409);
INSERT INTO `user` VALUES (9, '18722229999', '欧阳锋', 'e10adc3949ba59abbe56e057f20f883e', 60, 1, 1, 1554282409);
INSERT INTO `user` VALUES (10, '18733331111', '丘处机', 'e10adc3949ba59abbe56e057f20f883e', 69, 1, 1, 1554282409);
INSERT INTO `user` VALUES (11, '18733332222', '瑛姑', 'e10adc3949ba59abbe56e057f20f883e', 45, 1, 1, 1554282409);
INSERT INTO `user` VALUES (12, '18733333333', '王重阳', 'e10adc3949ba59abbe56e057f20f883e', 55, 1, 1, 1554282409);
INSERT INTO `user` VALUES (13, '18733334444', '穆念慈', 'e10adc3949ba59abbe56e057f20f883e', 19, 1, 1, 1554282409);
INSERT INTO `user` VALUES (14, '18733335555', '陈玄风', 'e10adc3949ba59abbe56e057f20f883e', 35, 1, 1, 1554282409);
INSERT INTO `user` VALUES (15, '18733336666', '曲灵风', 'e10adc3949ba59abbe56e057f20f883e', 42, 2, 1, 1554282409);
INSERT INTO `user` VALUES (16, '18733337777', '梅超风', 'e10adc3949ba59abbe56e057f20f883e', 32, 1, 1, 1554282409);
```
*****
### 2、SQL中的分页关键字
* `LIMIT m OFFSET n`
* `LIMIT m`: 每页显示的记录数量
* `OFFSET n`: 从指定的索引n开始显示
```mysql
SELECT * FROM user;
SELECT * FROM user LIMIT 0,5;
SELECT * FROM user LIMIT 5,5;
SELECT * FROM user LIMIT 5 OFFSET 5;
```
*****
### 3、偏移量计算公式
* offset = num * (page - 1)
*****
# :-: 二、Ajax原理
### 1、Ajax 是什么
* Ajax: (Asynchronous Javascript And XML)异步JavaScript和XML
* Ajax: 是指一种创建交互式网页应用的网页开发技术
* Ajax 是一种用于创建快速动态网页的技术
* Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
* 通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新
* 这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新
*****
### 2、XMLHTTPRequest
* XMLHttpRequest是一个浏览器接口,使得Javascript可以进行HTTP(S)通信
* 我们最熟悉应用就是创建**AJAX**对象
*****
### 3、案例
* 在不刷新页面的情况下, 从服务器获取数据并渲染到html中
```php
# php代码:get_cate.php
<?php
$pdo = new PDO('mysql:dbname=php', 'root','root');
$stmt = $pdo->prepare('SELECT * FROM `category`');
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo '<pre>' .print_r($result,true);
// echo json_encode($result);
```
```html
# index.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>电影分类</title>
</head>
<body>
<button>电影分类</button>
<ul>
</ul>
</body>
<script>
var btn = document.getElementsByTagName('button').item(0);
// 创建 Ajax对象
var request = new XMLHttpRequest();
btn.addEventListener('click', getCate, false);
// btn点击事件回调方法
function getCate(ev) {
// 监听请求
request.addEventListener('readystatechange', callBack, false);
// 配置请求
request.open('GET', 'get_cate.php', true);
// 发送请求
request.send(null);
// 从当前按钮上移除点击事件, 防止重复点击
ev.target.removeEventListener('click', getCate, false);
}
// Ajax的请求成功的回调方法
function callBack() {
if (request.readyState === 4) {
// 控制台检查
// console.log(request.responseText);
var data = JSON.parse(request.responseText);
// JSON 转 JS对象
// console.log(data);
// 循环生成<li>
var ul = document.getElementsByTagName('ul').item(0);
data.forEach(function (index){
// console.log(index['alias']);
var li = document.createElement('li');
li.innerText = index['alias'];
ul.appendChild(li);
});
}
}
</script>
</html>
```
*****
# :-: 三、Ajax分页
### 1. 服务器返回的数据格式
* COUNT 统计表中记录的一个函数,返回匹配条件的行数
* CEIL 浮点数向上取正
* LEFT 从左开始截取字符串
* CONCAT 将多个字符串连接成一个字符串
```php
# php代码:get_movies.php
<?php
// 获取当前要显示的页数
$page = intval($_GET['p'] ?? 1);
$pdo = new PDO('mysql:dbname=php', 'root', 'root');
// 每页显示数量
$num = 5;
// 总页数: 需要分二步, 第一求出总记录数量, 第二总记录数量除以每页显示的记录数量,再向上取整
$sql = "SELECT CEIL(COUNT(`mov_id`)/{$num}) FROM `movies`";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$pages = $stmt->fetchColumn(0);
// 每页的显示起止位置: 偏移量
// 偏移量 = 当前显示数量 * (当前页码 - 1)
$offset = $num * ($page - 1);
$sql = "SELECT `mov_id`,`name`, CONCAT(LEFT(`detail`,20),'...') AS `detail` FROM `movies` LIMIT {$num} OFFSET {$offset} ";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$movies = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['pages'=>$pages, 'movies'=>$movies]);
```
*****
### 2. 前端分页条
```php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最新影视剧介绍</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid black;
}
thead > tr{
background-color: lightblue;
}
ul, li {
padding: 0;
margin: 5px auto;
list-style: none;
text-align: center;
overflow: hidden;
}
li {
display: inline-block;
width: 30px;
height: 20px;
border: 1px solid black;
margin-left: 3px;
}
li:hover {
background-color: lightblue;
cursor: pointer;
}
/*设置当前页高亮样式*/
.active {
background-color: lightblue;
}
</style>
</head>
<body>
<table>
<caption>最新影视剧介绍</caption>
<thead>
<tr>
<th>序号</th>
<th>片名</th>
<th>简介</th>
</tr>
</thead>
<tbody id>
<!--这里显示影视信息列表-->
<tr>
<td>3</td>
<td>如果可以这样爱</td>
<td>一对已婚男女突然徇情自杀,以为可以结束这...</td>
</tr>
</tbody>
</table>
<ul>
<li class="active">1</li>
<li class="">2</li>
</ul>
</body>
</html>
```
### 3. 数据获取与渲染
```php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最新影视剧介绍</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid black;
}
thead > tr{
background-color: lightblue;
}
ul, li {
padding: 0;
margin: 5px auto;
list-style: none;
text-align: center;
overflow: hidden;
}
li {
display: inline-block;
width: 30px;
height: 20px;
border: 1px solid black;
margin-left: 3px;
}
li:hover {
background-color: lightblue;
cursor: pointer;
}
/*设置当前页高亮样式*/
.active {
background-color: lightblue;
}
</style>
</head>
<body>
<table>
<caption>最新影视剧介绍</caption>
<thead>
<tr>
<th>序号</th>
<th>片名</th>
<th>简介</th>
</tr>
</thead>
<tbody id>
<!--这里显示影视信息列表-->
</tbody>
</table>
<ul>
<!--这里翻页-->
</ul>
</body>
</html>
<script>
// 获取表格显示区
var tbody = document.getElementsByTagName('tbody').item(0);
// 获取页码显示区
var ul = document.getElementsByTagName('ul').item(0);
// 当前页码: 默认显示第一页
var p = <?=$_GET['p'] ?? 1?>;
// 创建 Ajax对象
var request = new XMLHttpRequest();
// 监听文档的load事件,在页面加载完成后通过Ajax方式获取数据
window.addEventListener('load', showData, false);
// load事件方法
function showData() {
// 监听Ajax成功回调
request.addEventListener('readystatechange', getData, false);
// 配置请求
request.open('GET', 'get_movies.php?p='+p, true);
// 发送请求
request.send(null);
}
function getData() {
if (request.readyState === 4) {
// console.log(request.responseText);
// 1. 获取Ajax返回的数据并解析为JavaScript变量
var obj = JSON.parse(request.responseText);
var pages = obj['pages'];
var movies = obj['movies'];
// 2. 生成表格数据
var str = '';
movies.forEach(function (movie) {
str += '<tr>';
str += '<td>' + movie['mov_id']+ '</td>';
str += '<td>' + movie.name+ '</td>';
str += '<td>' + movie.detail+ '</td>';
str += '</tr>';
});
// 将数据添加到表格中
tbody.innerHTML = str;
// 性能优化建议: 使用文档片段统一添加,以减少DOM操作,提升渲染效率
// var frag = document.createDocumentFragment();
// movies.forEach(function (movie) {
// var tr = document.createElement('tr');
// for (var key in movie) {
// var td = document.createElement('td');
// td.innerHTML = movie[key];
// tr.appendChild(td);
// }
// frag.appendChild(tr);
// });
// tbody.appendChild(frag);
// 3. 生成页码
for (var i = 1; i <= pages; i++) {
// 设置当前页码是否高亮?
var active = (i === p) ? 'active' : '';
ul.innerHTML += '<li class="'+ active +'">' + i + '</li>';
// 供参考的,规范的DOM语法
/*
var li = document.createElement('li');
li.appendChild(document.createTextNode(i.toString()));
if (p === i) li.classList.add('active');
ul.appendChild(li);
*/
}
}
}
// 给页码添加点击事件
ul.addEventListener('click', set_page, false);
function set_page(ev) {
console.log(ev.target.innerText);
location.search = '?p=' + ev.target.innerText;
}
// 作业:
// 添加上一下, 下一页功能, 注意判断页码越界的问题, 例如到了第一页再前翻怎么处理, 到了最后一页再后翻如何处理?
</script>
```
- 序言
- PHP基础
- 认识PHP
- 环境安装
- PHP语法
- 流程控制
- PHP数组
- PHP函数
- PHP类与对象
- PHP命名空间
- PHP7新特性
- PHP方法库
- PHP交互
- 前后端交互
- 项目常规开发流程
- MySQL数据库
- 会话控制
- Ajax分页技术
- 细说函数
- 类与对象
- 对象进阶
- 类与对象进阶
- OOP面向对象
- 设计模式
- 路由与模板引擎
- 异常类
- PHP爬虫
- PHP抓取函数
- PHP匹配函数
- 正则表达式
- PHP字符串函数
- 抓取实战
- PHP接口
- 了解接口
- PHP插件
- PHPSpreadsheet
- ThinkPHP6
- 安装
- 架构
- 数据库
- 数据库操作
- 视图
- 模版
- 模型
- 杂项
- 命令行
- 交互
- 微信小程序
- 介绍
- 配置
- 组件
- 交互
- API
- 其他知识
- 百度小程序
- 介绍
- 配置
- 组件
- 交互
- API
- 其他知识
- Linux
- 服务器上线流程
- 安装svn
- MySQL
- 认识MySQL
- MySQL函数
- 杂项
- composer依赖管理工具