直播造轮子-分页

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

不信我撸给你看。

一、应用场景

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

裸着的时候长得像这样:

二、撸起袖子,甩开膀子

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

})
时间: 2024-10-13 12:17:33

直播造轮子-分页的相关文章

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端系统打印经常使用的场景. 1.一种是类似票务方面的系统需要打印固定格式的票据.比如景点门票.车票.电影票. 这种基本是根据模板调整位置套打. 2.还有一种是交易小票,比如商超POS小票,打印长度会随着内容的大小自动伸缩. 这种就不仅仅是固定格式的套打了,还得计算数据行以适应不同的打印长度. 打印方式

Vue 造轮子

这是一门面向「初级和中级前端开发者」的 Vue 系统课. 这门课我酝酿了很久,这周终于开始直播了,目前已有 30 多个小伙伴报名. 想系统掌握 Vue 的同学可以继续往下看.  百度云盘 课程内容 UI 设计稿(未完工,更新中) 学习用 Vue 造轮子(有我自己制作的 UI 稿,标注齐全,需求明确) 通过造轮子完全掌握 Vue 的用法 了解 Vue 的周边工具,如单元测试工具.Vuex.Vue Router 等 目前共有 28 节课,涵盖表单控件.日期选择器.表格组件.Tree 组件.Sugge

python 造轮子(一)——序列与字典

虽然说造轮子很少用了,什么底层东西很少写,但是还是很想学扎实,还是好多东西还是的会,没有底层的支持,比较高级的库学起来还是很困难的. 序列的普遍用法: 1 #-*-coding:utf8-*- 2 3 #索引 4 l = [1,2,3,4] 5 t = (1,2,3,4) 6 d = {1:1,2:2,3:3,4:4} 7 8 9 print l[0] 10 print t[0] 11 print d[1] #键索引 12 13 #切片 14 15 print l[0:5] 16 print t

GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。

1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便地使用所有版本的Android动作栏的设计模式. 对于Android 4.0及更高版本,ActionBarSherlock可以自动使用本地ActionBar实现,而对于之前没有ActionBar功能的版本,基于Ice Cream Sandwich的自定义动作栏实现将自动围绕布局.能够让开发者轻松开发

我们为什么喜欢重新造轮子

不要重新造轮子,是英文don't re invite wheel的直译.什么是轮子呢,我们一般认为一个通用中间件或框架,和实际业务没有直接关系的代码,就是轮子.这些代码虽然不是实质的业务逻辑,但是在一个项目中往往是担当骨架的作用. 程序员新手的眼中,这些代码就是经验的象征.在很多项目组中,只有经验丰富的老程序员才有机会去设计和选择这些轮子.可以设计可重用的干货代码,也就成为很多对技术有追求的程序员的努力方向.有几年工作经验,在技术上寻求发展的程序员大多都会自己设计和实现一些经典的轮子,这也成为了

Hybrid App Development: 二、关于造轮子以及在Xcode iOS应用开发中加入Cordova

转载请注明出处:http://www.cnblogs.com/xdxer/p/4111552.html [ctrl+左键点击图片可以查看原图] 在上一篇关于Hybrid App Development的文章中,我讨论了一下在iOS下UIWebView的使用方法.但是光使用一个UIWebView所提供的功能还是完全不能满足我们的需求.   关于造轮子的思考: 在UIKit中的UIWebView虽然已经提供了很多功能了,比如JavaScript和Objc之间的通信.但是考虑到一个问题,如果在Hybr

避免重复造轮子的UI自动化测试框架开发

一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览器的基本上底层都是selenium,驱动无线app和浏览器基本是appium.monkey之类的,底层都是基于官方支持的自动化测试框架开发而来,然后上层又做了各种封装 首先在开始计划开发自动化时,第一步是了解目前已有的自动化开发技术,上面说了,最底层的就那几种,根据实际要去测试的业务需求选择合适的自

第27篇 重复造轮子---模拟IIS服务器

在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西是一个更好的理解和使用.   当你打开一个网页时,你会看到一个html页面的呈现,当然这是一个完整的Http的请求和响应的过程,无非是对HTML+CSS+JS一个综合的产物,在这个过程中浏览器请求数据的过程中会发出一个有一个格式的字符串(基于http协议生成的http请求报文),服务器在接收这样的一

Js造轮子,基础篇

在js中,只要不是在函数内部声明的函数都是全局变量了,如果代码量大的情况全局变量的污染是非常可怕的,所以需要造轮子声明自己的变量和自己的全局变量和函数方法 一,声明一个对象 先简单的声明一个对象tool={},这样就可以了,这样一个简单的全局对象就弄好了 二,声明方法和变量 这时候定义方法和变量就可以这样了 1 window.tool = {} 2 window.tool.cip = localStorage.cip; 3 4 //url 5 tool.urlHeader = 'http://1