虽说分页已经被人们撸过无数个了,但是目测还没有一个有我撸的好的》-《
不信我撸给你看。
一、应用场景
我需要这样一个分页组件,它有首页、上一页、上一组、一组页码、下一组、下一页、末页,可以自由控制一组页数,还得是个组件。
裸着的时候长得像这样:
二、撸起袖子,甩开膀子
1、先想好工作原理
已知:条目总数:total,页长:pageSize,初始页码:pageIndex。
目的:根据已知条件算出是否有首页(first)、上一页(prev)、上一组(blockLeft)、一组页码(当前页pageIndex居中)(pageBlock)、下一组(blockRight)、下一页(next)、末页(end)。
像我这样初中开始数学就没及格过的都能算出来,我就不啰嗦了,直接放个伪代码:
/*fileds*/ var total,pageSize,pageIndex,halfBlockSize; var pageCount = Math.ceil(total/pageSize); var pageBlock = function(){ for: pageIndex-halfBlockSize->pageIndex+halfBlockSize{ if:(item>0&&item<pageCount) push to array } return array; }; var hasBlockLeft = (pageBlock[0]-1)>halfBlockSize; var hasBlockRight = (pageCount-pageBlock[length-1])>halfBlockSize; var hasPrev = pageIndex>1; var hasNext = pageIndex<pageCount; /*click functions*/ var prev = function(){pageIndex--;} var first = function(){pageIndex = 1;} var blockLeft = function(){pageIndex =pageIndex-halfBlockSize*2;} var index = function(){pageIndex = index;} var blockRight = function(){pageIndex = pageIndex+halfBlockSize*2;} var end = function(){pageIndex = pageCount} var next = function(){pageIndex++;}
核心"算法"已经出来了,那么接下来渲染界面就可以了,可以用js/jquery/vue/react等等操作dom,我比较土,用knockoutJS。
view:
<div data-bind="with:pager"> <a href="javascript:void(0)" data-bind="visible:pageCount()>1,click:first">First</a> <a href="javascript:void(0)" data-bind="visible:hasPrev,click:prev">< Prev</a> <a href="javascript:void(0)" data-bind="visible:hasBlockLeft,click:blockLeft"><<</a> <!--ko foreach:pageBlock--> <a href="javascript:void(0)" data-bind="text:$data,click:$parent.index.bind($data)">Index</a> <!--/ko--> <a href="javascript:void(0)" data-bind="visible:hasBlockRight,click:blockRight">>></a> <a href="javascript:void(0)" data-bind="visible:hasNext,click:next">Next ></a> <a href="javascript:void(0)" data-bind="visible:pageCount()>1,click:end">End</a> </div>
viewmodel:
define(['knockout'], function (ko) { var pager = function (total, pageSize, pageIndex, halfBlockSize, getPageData) { var self = this; self.total = ko.observable(total); self.halfBlockSize = halfBlockSize == null ? 2 : halfBlockSize; self.pageSize = ko.observable(pageSize); self.pageIndex = ko.observable(pageIndex == null ? 1 : pageIndex); self.pageCount = ko.computed(function () { return Math.ceil(self.total() / self.pageSize()); }); self.hasNext = ko.computed(function () { return self.pageIndex() < self.pageCount() && self.pageCount() > 1; }); self.hasPrev = ko.computed(function () { return self.pageIndex() > 1 && self.pageCount() > 1; }); self.pageBlock = ko.computed(function () { var start = self.pageIndex() - self.halfBlockSize; var len = self.pageIndex() + self.halfBlockSize; var arr = []; for (var i = start; i <= len; i++) { if (i > 0 && i <= self.pageCount()) { arr.push(i); } } return arr; }); self.hasBlockLeft = ko.computed(function () { return (self.pageBlock()[0] - 1) > self.halfBlockSize; }); self.hasBlockRight = ko.computed(function () { return (self.pageCount() - self.pageBlock()[self.pageBlock().length - 1]) > self.halfBlockSize; }); self.isInited = false; self.handlePageIndex = ko.computed(function () { if (!self.isInited) { self.isInited = true; return self.pageIndex();//Let ko know this function is with self.pageIndex(); } getPageData(self.pageIndex()); return 0; }) /*click functions*/ self.prev = function () { self.pageIndex(self.pageIndex() - 1); }; self.first = function () { self.pageIndex(1); }; self.blockLeft = function () { self.pageIndex(self.pageIndex() - self.halfBlockSize * 2); }; self.index = function (i) { if (i == self.pageIndex()) { getPageData(i);//While current pageIndex was clicked,I'll call the function manually. } else { self.pageIndex(i);//While current pageIndex was changed,it'll call the function automatically. } }; self.blockRight = function () { self.pageIndex(self.pageIndex() + self.halfBlockSize * 2); }; self.end = function () { self.pageIndex(self.pageCount()); }; self.next = function () { self.pageIndex(self.pageIndex() + 1); } /*click functions*/ }; return { vm: pager } });
遵循AMD规范,方便异步加载。
css的话,自由发挥吧。这里就不贴了。
如此已经可以当成组件来用,加载view和viewmodel即可,例如:
render('view');
require(['knockout','pager'],function(ko,pager){ var pg = new pager.vm(100, 1, 15, 5, function (i) { console.log("I'm get " + i); }); })