前言
最近正式加入了前端坑,看了几篇关于jquery插件的文章,控制不住洪荒之力想自己也写写。点开百度,正好看到了百度的分页看起来挺舒服,于是就它了。纯当练手,如果文章中发现问题,还希望大佬可以指正。
观察
首先我们看看百度分页的图片(并没有给公司打广告):
有兴趣的同学只需要点开百度就行了,经过观察,我们发现他的分页有以下需要注意的地方:
- 单数页码上面的脚印高一点,复数低一点,当前页图片是个logo标志;
- 当前页是第一页不显示上一页,同理最后一页不显示下一页;
- 最多显示10个页码,10个页码以内按顺序展示就行;
- 当前页码大于5小于总页码-4的时候,总是在第六的位置显示(这个逻辑可以自行体验一下)
经过分析,只有最后一个有一些逻辑要写,分析好了要做的东西,下面就开做啦。
代码
首先我们可以简单考虑一下我们做的插件需要对外开放的配置,也是为了拓展性,这里我们在插件中定义了默认的配置:
var defaults = {
pageSize: 10,
count: 100,
current: 1,
prevDes: "<上一页",
nextDes: "下一页>",
updateSelf: true,
callback: null
};
// 插件配置合并
this.oConfig = $.extend(defaults, config);
var self = this;
基于基本需求的考虑,定义了总数count,每页数目pageSize,当前页是第几页current,上一页下一页的文案。由于需求中,我们不一定是点击了页面更新的还是当前的插件,更多的是直接跳转,所以我们添加了标记updateSelf以及点击的反馈回调callback。初始化中我们接收调用者传递的参数config,合并之后使用oConfig。
接下来就是正式根据配置信息绘制我们的页面了,根据我们一开始的观察分析,绘制整个分页插件采用的逻辑如下:
1.判断当前页是否为第一页,不是,则添加上一页元素。
2.遍历绘制页码,那么根据百度分页的逻辑,我们定义遍历的起始和结束变量start和end,总页码数pageCount,当前页码为current:
- 当总页码小于10的时候,start为1,end为pageCount;
- 总页码大于10,当前页码小于等于5,start为1,end为10;
- 总页码大于10,当前页码小于等于总页码数-4,start为pageCount-9,end为pageCount
- 总页码大于10,当前页介于上两个之间,start为current - 5,end为current + 4;
如此一来,遍历的起止位置就有了,然后通过遍历绘制每个页码,当然此处需要判断一下页码的单复数来决定脚印的位置。
3.判断当前页是否为最后一页,不是,则添加下一页元素。
逻辑分析明了了,代码自然就很清晰了,首先是分页插件js的所有代码
(function ($, window) {
$.fn.CustomPage = function (config) {
// 默认配置
var defaults = {
pageSize: 10,
count: 100,
current: 1,
prevDes: "<上一页",
nextDes: "下一页>",
updateSelf: true,
callback: null
};
// 插件配置合并
this.oConfig = $.extend(defaults, config);
var self = this;
// 初始化函数
var init = function () {
// 初始化数据
updateConfig(self.oConfig);
// 事件绑定
bindEvent();
};
// 更新方法
var updateConfig = function (config) {
typeof config.count !== 'undefined' ? self.count = config.count : self.count = self.oConfig.count;
typeof config.pageSize !== 'undefined' ? self.pageSize = config.pageSize : self.pageSize = self.oConfig.pageSize;
typeof config.current !== 'undefined' ? self.current = config.current : self.current = self.oConfig.current;
self.pageCount = Math.ceil(self.count / self.pageSize);
format();
};
var format = function () {
var current = self.current;
var count = self.pageCount;
var html = '<div class="page-container"><ul>';
if (current != 1)
html += '<li class="page-item page-prev page-action-text">' + self.oConfig.prevDes + '</li>';
var start = 1;
var end = count;
if (count > 10) {
if (current <= 5) {
start = 1;
end = 10;
} else if (current >= count - 4) {
start = count - 9;
end = count;
} else {
start = current - 5;
end = current + 4;
}
}
for (var i = start; i <= end; i++) {
html += getItem(i);
}
if (current != count)
html += '<li class="page-item page-next page-action-text">' + self.oConfig.nextDes + '</li>';
html += '</ul></div>';
self.html(html);
};
var getItem = function (i) {
var item = '';
var current = (i == self.current);
item += '<li class="page-item" data-page="' + i + '"><div class="page-icon-content">';
if (current) {
item += '<div class="page-icon-current page-icon-content"></div>';
item += '</div><span class="page-text-current">' + i + '</span></li>';
} else {
item += '<div class="' + (i % 2 == 0 ? 'page-icon-type1' : 'page-icon-type2') + ' page-icon"></div>';
item += '</div><span class="page-text">' + i + '</span></li>';
}
return item;
};
//点击事件
var bindEvent = function () {
self.on('click', '.page-item', function () {
var current;
if ($(this).hasClass('page-prev')) {
current = Math.max(1, self.current - 1);
} else if ($(this).hasClass('page-next')) {
current = Math.min(self.pageCount, self.current + 1);
} else {
current = parseInt($(this).data('page'));
}
self.oConfig.callback && self.oConfig.callback(current);
if (self.oConfig.updateSelf) {
self.current = current;
format();
}
})
};
// 启动
init();
//对外提供更新方法
this.update = function (config) {
updateConfig(config);
};
// 链式调用
return self;
};
})(jQuery, window);
然后是css样式代码,大家随便画画哈:
.page-container {
color: rgb(0, 0, 204);
font-size: 14px;
background-color: white;
}
.page-container ul {
overflow: hidden;
display: flex;
text-align: center;
justify-content: center;
}
.page-container ul, .page-container li {
list-style: none;
}
.page-item {
margin-right: 9px;
}
.page-icon-content {
width: 36px;
height: 30px;
}
.page-icon {
width: 24px;
height: 24px;
line-height: 24px;
margin-left: auto;
margin-right: auto;
cursor: pointer;
overflow: hidden;
border-style:none;
background: url(https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/global/img/icons_5859e57.png) no-repeat -144px -288px;
}
.page-icon-type1 {
position: relative;
top: -2px;
}
.page-icon-type2 {
position: relative;
top: 3px;
}
.page-icon-current {
width: 24px;
height: 24px;
line-height: 24px;
display: inline-block;
cursor: pointer;
overflow: hidden;
background: url(https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/global/img/icons_5859e57.png) no-repeat -96px -288px;
}
.page-text {
width: 34px;
height: 34px;
border: 1px solid #e1e2e3;
cursor: pointer;
display: block;
line-height: 34px;
}
.page-text-current {
width: 36px;
height: 36px;
cursor: pointer;
display: block;
line-height: 36px;
}
.page-text:hover,.page-action-text:hover {
border: 1px solid rgb(0, 0, 204);
}
.page-action-text {
height: 34px;
padding: 0 18px;
border: 1px solid #e1e2e3;
cursor: pointer;
display: block;
line-height: 34px;
margin-top: 30px;
background-color: white;
}
最后就是调用者的调用了,我们分为两种情况,自身更新以及跳转更新来应对不同场景:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>仿百度分页小插件</title>
<link rel="stylesheet" href="customPage.css">
<script type="text/javascript" src="jquery-1.11.2.js"></script>
<script type="text/javascript" src="customPage.js"></script>
<script>
$(function () {
var page = $(".page").CustomPage({
pageSize: 10,
count: 160,
current: 1
});
var page2 = $(".page2").CustomPage({
pageSize: 10,
count: 120,
current: 5,
updateSelf: false,
callback: function (selected) {
alert(selected);
}
});
});
</script>
</head>
<body>
<div class="page"></div>
<div class="page2"></div>
</body>
</html>
当然你也可以通过page变量来调用我们给外部提供的update方法来更新变化。整个插件的效果如下:
附上演示地址:
http://jsrun.net/hPYKp
github地址
https://github.com/bestneville/JqueryPagePlugin