话说那天我正坐在电脑前,手里捧着一杯82年的速溶咖啡,突然接到产品经理的电话:“老张,咱们那个列表页能不能做成无刷新分页?每次翻页都刷新页面,用户体验太差了!”我一听,这不就是Ajax分页的需求吗?于是我拍了拍胸脯:“没问题,包在我身上!”
于是我开始了一段与Ajax无刷新分页的“爱情故事”。首先,得明确一下需求:我们有一个用户列表,数据量比较大,所以需要分页展示。用传统的方式,每次翻页都会刷新整个页面,用户体验确实不太好。现在要用Ajax实现无刷新分页,也就是点击分页按钮后,只更新列表部分的内容,页面其他部分保持不变。
准备工作
准备好我们的后端接口。假设我们用的是PHP,数据库是MySQL,表结构大概是这样的:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL
);
现在我们需要一个分页接口,接收页码和每页显示的条数,返回对应的数据。假设我们的接口是get_users.php
,代码如下:
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10;
$offset = ($page - 1) $limit;
$conn = new mysqli('localhost', 'root', 'password', 'test_db');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT
FROM users LIMIT $offset, $limit";$result = $conn->query($sql);
$users = [];
while ($row = $result->fetch_assoc()) {
$users[] = $row;
}
echo json_encode($users);
$conn->close();
?>
这个接口很简单,接收page
和limit
参数,然后从数据库中查询对应的数据,最后返回JSON格式的数据。
前端实现
接下来就是前端的工作了。我们先用一个简单的HTML结构来展示用户列表和分页按钮:
ID |
---|
Name |
---|
然后我们写一个JavaScript函数loadPage
,用来加载指定页码的数据:
function loadPage(page) {
const limit = 10;
const xhr = new XMLHttpRequest();
xhr.open('GET', get_users.php?page=${page}&limit=${limit}
, true);
xhr.onload = function() {
if (xhr.status === 200) {
const users = JSON.parse(xhr.responseText);
const tbody = document.querySelector('#user-list tbody');
tbody.innerHTML = '';
users.forEach(user => {
const row = document.createElement('tr');
row.innerHTML =
${user.id} | ${user.name} | ${user.email} |
tbody.appendChild(row);
});
} else {
console.error('Request failed. Status:', xhr.status);
}
};
xhr.send();
}
这个函数的作用是发送一个Ajax请求,获取指定页码的数据,然后将数据插入到表格的tbody
中。
动态生成分页按钮
现在我们的分页按钮是写死的,实际应用中,分页按钮应该是动态生成的。假设我们从后端接口中获取到了总页数,我们可以这样生成分页按钮:
function generatePaginationButtons(totalPages) {
const paginationDiv = document.getElementById('pagination');
paginationDiv.innerHTML = '';
for (let i = 1; i <= totalPages; i++) {
const button = document.createElement('button');
button.innerText = i;
button.onclick = () => loadPage(i);
paginationDiv.appendChild(button);
}
}
这段代码会根据总页数动态生成分页按钮,并且为每个按钮添加点击事件,点击按钮时会调用loadPage
函数加载对应的数据。
分页参数的传递
在实际应用中,分页参数可能需要传递给后端接口。比如,我们可能需要根据某些条件进行筛选,或者在分页的同时进行排序。这时候,我们需要将分页参数和筛选条件一起传递给后端。例如:
function loadPage(page, filters) {
const params = new URLSearchParams({ page, limit, ...filters });
xhr.open('GET', get_users.php?${params.toString()}
, true);
const response = JSON.parse(xhr.responseText);
const users = response.data;
generatePaginationButtons(response.totalPages);
};
}
这里我们使用了URLSearchParams
来构建查询字符串,将分页参数和其他筛选条件一起传递给后端。后端接口需要根据这些条件进行查询,并返回对应数据。
处理分页边界情况
在实际开发中,我们还需要处理一些边界情况。比如:
用户点击的页码超过了总页数怎么办?
用户点击的页码小于1怎么办?
后端返回的数据为空怎么办?
这些问题我们都需要考虑。比如,我们可以对页码进行校验,确保页码在有效范围内:
if (page < 1) return;
if (response.data.length === 0) {
alert('没有更多数据了!');
return;
}
};
}
这里我们增加了对页码的校验,并且在后端返回空数据时给用户一个提示。
优化用户体验
为了让用户体验更好,我们还可以做一些优化:
在加载数据时显示一个加载动画,数据加载完成后隐藏。
使用防抖或节流技术,避免用户快速点击分页按钮时发送过多请求。
使用fetch
API代替XMLHttpRequest
,代码更简洁。
例如,我们在加载数据时显示一个加载动画:
const loader = document.createElement('div');
loader.className = 'loader';
document.body.appendChild(loader);
fetch(get_users.php?${params.toString()}
)
.then(response => response.json())
.then(response => {
document.body.removeChild(loader);
');
})
.catch(error => {
console.error('Request failed:', error);
}
这里我们使用了fetch
API,并且在加载数据时显示了一个加载动画,加载完成后移除。
总结
通过以上步骤,我们实现了一个简单的PHP Ajax无刷新分页功能。这个功能虽然看似简单,但在实际开发中可能会遇到很多问题,比如分页参数传递、边界情况处理、用户体验优化等。希望这篇文章能帮你少踩一些坑,顺利实现无刷新分页功能。