为了更好的掌握nodej.js,于是最近用node.js写了个小demo,发现node.js的库相对php还是少了许多。对于常用的分页类也没找到,于是就基于bootstrap自己写了一个。
不过,不得不吐槽一下,node.js的异步也很坑,,,在对数据库select的时候是异步的,所有依赖数据库返回的逻辑都要写在回调函数里面,阔是,如果有多个逻辑需要数据库层层返回,无限的层层嵌入,,,oh,god!还好,分页类嵌套两层就阔以了。当然,借助库,这些异步操作也可以改成同步进行。可见,异步虽然流弊闪闪也有它的缺点,当然咯,go语言的协程可以解决异步操作,但是代码表现形式依然是同步的,我大php在5.5版本中也加入了对协程的支持。
地址:https://github.com/liufee/nodejs
分页效果:
/* * @author liufee <job@feehi.com> * @link https://blog.feehi.com/wp-content/uploads * @description nodejs分页类 **/ var url = require('url'); module.exports = function(req, total, params){ this.total = total;//总记录数 this.perPage = 20;//每页显示多少条记录 this.pageListNum = 15;//分页按钮数量 this.pageSign = 'page';//分页标识符 this.totalPage = Math.ceil(this.total/this.perPage); this.req = req;//request对象 this.config = { "header" : '<span style="position:relative;top:8px;left:10px" class="rows">第%CURRENT%/%TOTAL%页</span>', 'first' : '<li><a href="%HREF%" aria-label="fisrt"><span aria-hidden="true">首页</span></a></li>', 'prev' : '<li><a href="%HREF%" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>', 'next' : '<li><a href="%HREF%" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>', 'last' : '<li><a href="%HREF%" aria-label="last"><span aria-hidden="true">尾页</span></a></li>', 'list' : '<li class="%STATUS%"><a href="%HREF%">%NUM%</a></li>',//要输出的分页列表模版 'theme' : '<nav><ul class="pagination">%FIRST% %PREV% %PAGES% %NEXT% %LAST% %HEADER%</ul></nav>' }; for(var key in params){ if(key == 'pageListNum') this.pageListNum = params[key]; if(key == 'pageSign') this.pageSign = params[key]; if(key == 'perPage') this.perPage = params[key]; if(key == 'config') this.config = params[key]; } this.parseUrl = function(){ var query = ''; var urls = url.parse(this.req.url, true); var query = this.req._parsedOriginalUrl.pathname+'?'; this.page = 1; for(var index in urls.query){ if( index != this.pageSign ){ query += index+'='+urls.query[index]+'&'; }else{ this.page = urls.query[index]; } } this.query = query+this.pageSign+'='; } this.parseUrl(); /*获取sql语句中limit部分*/ this.getLimit = function(){ if(this.page&&this.page>0){ var start = (this.page-1) * this.perPage; }else{ page = 1; var start = 1; } return "limit "+start+','+this.perPage; } this.getHeader = function(){ return this.config.header.replace(/%CURRENT%/, this.page).replace(/%TOTAL%/, this.totalPage); } this.getFirst = function(){ var first = ''; if(this.page != 1){ first = this.config.first.replace(/%HREF%/, this.query+1); } return first; } this.getPrev = function(){ var prev = ''; if(this.page != 1){ var i = parseInt(this.page)-1; prev = this.config.prev.replace(/%HREF%/, this.query+i); } return prev; } this.getNext = function(){ var next = ''; if(this.page<this.totalPage){ var i = parseInt(this.page)+1; next = this.config.next.replace(/%HREF%/, this.query+i); } return next; } this.getLast = function(){ var last = ''; if(this.page < this.totalPage){ last = this.config.last.replace(/%HREF%/, this.query+this.totalPage); } return last; } this.getPages = function(){ var nums = Math.ceil(this.pageListNum/2); var pages = ''; var temp = ''; if(this.page<=nums){//当前页不足显示分页数木的一半,从1-pageListNum for(var i=1; i<=this.pageListNum; i++){ var status = 'disable'; if(i == this.page){ status = 'active'; } temp = this.config.list.replace(/%STATUS%/, status).replace(/%HREF%/, this.query+i).replace(/%NUM%/, i); pages += temp; } }else{//从当前页,向前一半,向后一半 for(var j=nums; j>1; j--){//前半部分li i = this.page-j+1; temp = this.config.list.replace(/%STATUS%/, 'disable').replace(/%HREF%/, this.query+i).replace(/%NUM%/, i); pages += temp; } pages += this.config.list.replace(/%STATUS%/, 'active').replace(/%HREF%/, this.query+this.page).replace(/%NUM%/, this.page); for(var j=1;j<nums;j++){//后半部分li i = parseInt(this.page)+j; if(i>this.totalPage) break; temp = this.config.list.replace(/%STATUS%/, 'disable').replace(/%HREF%/, this.query+i).replace(/%NUM%/, i); pages += temp; } } return pages; } this.showPage = function(){ var header = this.getHeader(); var first = this.getFirst(); var prev = this.getPrev(); var next = this.getNext(); var last = this.getLast(); var pages = this.getPages(); return this.config.theme.replace(/%HEADER%/, header).replace(/%FIRST%/, first).replace(/%PREV%/, prev).replace(/%PAGES%/, pages).replace(/%NEXT%/, next).replace(/%LAST%/, last); } }
使用方法:
var params = {//配置分页参数,pageListNum为显示页码按钮的数量:默认为15,perPage为每页显示的记录数:默认为20,pageSign为分页标识码:默认为page, config为分页模版 pageListNum : 15, perPage : 10, pageSign : "p", config : { "header" : '<span style="position:relative;top:8px;left:10px" class="rows">第%CURRENT%------%TOTAL%页</span>', 'first' : '<li><a href="%HREF%" aria-label="fisrt"><span aria-hidden="true">首页</span></a></li>', 'prev' : '<li><a href="%HREF%" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>', 'next' : '<li><a href="%HREF%" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>', 'last' : '<li><a href="%HREF%" aria-label="last"><span aria-hidden="true">尾页</span></a></li>', 'list' : '<li class="%STATUS%"><a href="%HREF%">%NUM%</a></li>',//要输出的分页列表模版 'theme' : '<nav><ul class="pagination">%FIRST% %PREV% %PAGES% %NEXT% %LAST% %HEADER%</ul></nav>' } } var p = new pg(req, results[0]['total'], params); var limit = p.getLimit(); var pageList = p.showPage();
这个分页类的实现思路完全是借用php的分页类实现的,只是把php语言翻译成node而已。因为我的小demo前端是基于bootstrap的,时间紧急,没有支持传入参数来替换显示分页的样式,有空再完善一下。在写的过程中,发现node的封装,很多都是在js层封装的,不似php,都是在c底层封装的,像get、post、cookie、session等值的获取与操作都集成在zend引擎核心里面了,甚至不是作为一个扩展提供,而node.js提供的内置对象,只是把底层基于http协议发送过来的socket连接数据读取到,解析还要靠js层的封装。
转载请注明:飞嗨 » node.js分页类