实现效果
1、封装类部分:<项目根目录>/extend/lib/Paginator.php
<?php
namespace lib;
class Paginator
{
//总记录
private $total;
//每页显示多少条
private $limit;
//当前页码
private $page;
//总页码
private $pcount;
//分页步长
private $both;
/**
* 构造
*/
public function __construct($total, $limit = 10, $both = 2)
{
if (!('integer' === gettype($total) && $total)) {
$total = 0;
}
if (!('integer' === gettype($limit) && $limit)) {
$limit = 10;
}
if (!('integer' === gettype($both) && $both)) {
$limit = 2;
}
$this->total = $total;
$this->limit = $limit;
$this->both = $both;
$this->pcount = ceil($this->total / $this->limit);
$this->page = $this->picker();
if ($this->page >= $this->pcount) {
$this->page = $this->pcount;
}
}
/*
* 生成分页
* mode参数说明:0-完整输出;1-仅输出数字分页;2-输出数字+前后;3-输出数字+首尾
*/
public function build($mode = 0)
{
$out = '';
if (!('integer' === gettype($mode) && in_array($mode, array(0, 1, 2, 3)))) {
$mode = 0;
}
if (in_array($mode, array(0, 3))) {
$out .= $this->first();
}
if (in_array($mode, array(0, 2))) {
$out .= $this->prev();
}
$out .= $this->plist();
if (in_array($mode, array(0, 2))) {
$out .= $this->next();
}
if (in_array($mode, array(0, 3))) {
$out .= $this->last();
}
return $out;
}
/*
* 当前页码拾取器
*/
private function picker()
{
$page = isset($_POST['page']) ? $this->format($_POST['page']) : 0;
if (!$page) {
return 1;
}
if ($page > $this->pcount) {
$page = $this->pcount;
}
return $page;
}
/*
* 数字格式化
*/
private function format($num)
{
$type = gettype($num);
if ('boolean' === $type) {
return $num ? 1 : 0;
} elseif (in_array($type, array('integer', 'string'))) {
return preg_match('/^[0-9]+$/', $num) ? (int) $num : 0;
} else {
return 0;
}
}
/*
* 数字页码
*/
private function plist()
{
$out = '';
for ($i = $this->both; $i >= 1; $i--) {
$page = $this->page - $i;
if ($page < 1) {
continue;
}
$out .= '<a data-page-num="' . $page . '" href="javascript:;">' . $page . '</a>';
}
$out .= '<a href="javascript:;" class="cur">' . $this->page . '</a>';
for ($i = 1; $i <= $this->both; $i++) {
$page = $this->page + $i;
if ($page > $this->pcount) {
break;
}
$out .= '<a data-page-num="' . $page . '" href="javascript:;">' . $page . '</a>';
}
return $out;
}
/*
* 首页
*/
private function first()
{
$dist = $this->both + 1;
if ($this->page > $dist) {
$out = '<a data-page-num="1" href="javascript:;" class="flex-ac icon icon-first"></a>';
return $out;
}
}
/*
* 上一页
*/
private function prev()
{
if ($this->page == 1) {
return '';
}
$page = $this->page - 1;
$skip = $this->page - ($this->both * 2) - 1;
$out = '<a data-page-num="' . $page . '" href="javascript:;"';
$out .= ' class="flex-ac icon icon-prev"></a>';
if ($skip > 0) {
$out .= '<a data-page-num="' . $skip . '"';
$out .= ' href="javascript:;">…</a>';
}
return $out;
}
/*
* 下一页
*/
private function next()
{
if ($this->page == $this->pcount) {
return '';
}
$out = '';
$page = $this->page + 1;
$skip = $this->page + ($this->both * 2) + 1;
if ($skip < $this->pcount) {
$out .= '<a data-page-num="' . $skip . '"';
$out .= ' href="javascript:;">…</a>';
}
$out .= '<a data-page-num="' . $page . '" href="javascript:;"';
$out .= ' class="flex-ac icon icon-next"></a>';
return $out;
}
/*
* 尾页
*/
private function last()
{
$dist = $this->pcount - $this->page;
if ($dist > $this->both) {
$out = '<a data-page-num="' . $this->pcount . '" href="javascript:;"';
$out .= ' class="flex-ac icon icon-last"></a>';
return $out;
}
}
}
调用示例
$paginator = new Paginator(10000);
$paginate = $paginator->build();
输出html
<div class="flex-ac pages">
<a data-page-num="" href="javascript:;" class="flex-ac icon icon-first"></a>
<a data-page-num="" href="javascript:;" class="flex-ac icon icon-prev"></a>
<a data-page-num="" href="javascript:;">...</a>
<a data-page-num="" href="javascript:;">4</a>
<a data-page-num="" href="javascript:;">5</a>
<a data-page-num="" href="javascript:;" class="cur">6</a>
<a data-page-num="" href="javascript:;">7</a>
<a data-page-num="" href="javascript:;">8</a>
<a data-page-num="" href="javascript:;">...</a>
<a data-page-num="" href="javascript:;" class="flex-ac icon icon-next"></a>
<a data-page-num="" href="javascript:;" class="flex-ac icon icon-last"></a>
</div>
2、js脚本部分
<script type="text/javascript">
//query转json
function buildJsonByQuery() {
var json = {};
var query = decodeURIComponent(location.search.substring(1));
var args = query.split('&');
var pair = [];
for (var i = 0; i < args.length; i++) {
pair = args[i].split('=');
if (pair[0].length > 0) {
json[pair[0]] = pair[1];
}
}
return json;
}
//json转query
function buildQueryByJson(json) {
var query = Object.keys(json).map(function(key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]);
}).join('&');
return query;
}
//页面脚本
$(function() {
//携带页码跳转方式
$(document).on('click', '[data-page-num]', function(e) {
e.stopPropagation();
var url = location.pathname;
var query = buildJsonByQuery();
var page = $(this).attr('data-page-num');
query.page = page;
url += '?' + buildQueryByJson(query);
location.href = url;
});
//ajax请求方式
$(document).on('click', '[data-page-num]', function(e) {
e.stopPropagation();
var url = location.pathname;
var query = buildJsonByQuery();
var headers = {
Accept: 'application/json;charset=utf-8'
};
var page = $(this).attr('data-page-num');
query.page = page;
$.ajax({
async: true,
type: 'POST',
url: url,
headers: headers,
data: query,
dataType: 'JSON',
beforeSend: function() {
console.log('beforeSend');
},
success: function(res) {
console.log(res);
},
error: function(err) {
console.log(err);
}
});
});
});
</script>
3、css样式部分
:root {
--primary-color: #1890ff;
--primary-color-hover: #40a9ff;
--primary-color-active: #096dd9;
}
html,
body {
width: 100%;
height: 100%;
line-height: 1;
font-family: -apple-system, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji;
font-size: 14px;
color: rgba(0, 0, 0, .85);
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
a {
text-decoration: none;
color: #1890ff;
color: var(--primary-color);
outline: none;
cursor: pointer;
}
a:hover {
color: #40a9ff;
color: var(--primary-color-hover);
}
a:active {
color: #096dd9;
color: var(--primary-color-active);
}
a:active,
a:hover,
a:focus {
outline: 0;
}
.icon {
/*省略*/
}
.icon:before {
/*省略*/
}
.icon.icon-prev:before {
/*省略*/
}
.icon.icon-next:before {
/*省略*/
}
.icon.icon-first:before {
/*省略*/
}
.icon.icon-last:before {
/*省略*/
}
.flex-ac {
display: -webkit-flex;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
align-items: center;
}
.pages {
width: 100%;
}
.pages>a {
display: block;
padding: 0 10px;
height: 28px;
border: 1px solid #d9d9d9;
line-height: 26px;
color: rgba(0, 0, 0, .85);
}
.pages>a:not(:last-child) {
border-right: none;
}
.pages>a:hover {
border-color: #40a9ff;
border-color: var(--primary-color-hover);
color: #40a9ff;
color: var(--primary-color-hover);
}
.pages>a:hover+a {
border-left-color: #40a9ff;
border-left-color: var(--primary-color-hover);
}
.pages>a:active {
border-color: #096dd9;
border-color: var(--primary-color-active);
color: #096dd9;
color: var(--primary-color-active);
}
.pages>a.cur {
border-color: #1890ff;
border-color: var(--primary-color);
color: #1890ff;
color: var(--primary-color);
cursor: not-allowed;
}
.pages>a.cur+a {
border-left-color: #1890ff;
border-left-color: var(--primary-color);
}
.pages>a.icon:before {
font-size: 12px;
}