:-: 一、分页原理

1、基本术语

# 为了测试方便,我们先增加一些数据
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中的分页关键字

SELECT * FROM user;
SELECT * FROM user LIMIT 0,5;
SELECT * FROM user LIMIT 5,5;
SELECT * FROM user LIMIT 5 OFFSET 5;

3、偏移量计算公式


:-: 二、Ajax原理

1、Ajax 是什么


2、XMLHTTPRequest


3、案例

# 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);
# 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. 服务器返回的数据格式

# 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. 前端分页条

<!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. 数据获取与渲染

<!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>