直播造轮子-分页

虽说分页已经被人们撸过无数个了,但是目测还没有一个有我撸的好的》-《

不信我撸给你看。

一、应用场景

我需要这样一个分页组件,它有首页、上一页、上一组、一组页码、下一组、下一页、末页,可以自由控制一组页数,还得是个组件。

裸着的时候长得像这样:

 二、撸起袖子,甩开膀子

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); }); })

 

posted @ 2016-07-29 16:36  蝌蝌  阅读(472)  评论(2编辑  收藏  举报