1.分页显示数据
准备工作:启动数据库服务,打开mongo.exe,启动nodejs服务。
浏览器地址:http://localhost:1234/ 会看见显示的数据。
我们要做的是分页显示数据,在预览时我们经常看见,现在news集合只有3条记录,我们增加到10条,作为操作使用。
刷新看见数据全部进来了,我们可以着手分页的工作了。
我们先简单分析分页原理:
首先地址上有当前页参数(get方法) 如变量 currentpage=1第一页,地址变为localhost:1234/?currentpage=1;
每页显示个数 如变量 count=3;
然后就是当前页显示记录 公式(currentpage-1)*3
第1页 0-2记录
第2页 3-5记录
类推;
记录总个数/每页个数 等于总页数,不整除+1页。
我们修改index.js的首页处理,get获取当前页数:
app.get('/',function(req, res){ var currentpage=req.query.currentpage?req.query.currentpage:1; model.model_index(currentpage,function(items){ res.render('index', { title: 'Express',hello: 'hello world!',arr: items }); }); });
获取参数currentpage的值,没有参数默认在第一页。
修改model.js的处理:
对于查询操作,mongoskin提供了非常丰富的处理,我们查看api,找到处理方法,假如是第一页,那么就该获取0-2记录的数据,
model.model_index=function(currentpage,callback){ var count=3; var offset=(currentpage-1)*count; db.bind('news'); db.news.find({},{limit: count, skip:offset}).toArray(function(err, items) { if (err) throw err; callback(items); db.close(); }); };
我对传入的参数做了处理,在find方法加入limit和skip高级处理,skip就是跳到第几条记录开始显示,limit就是往后查询几条,和mysql的limit语句类似。
我们查看首页数据:
显示3条,我们继续处理,我们首先要获取总记录数,然后算出总页数,把这个都要返回给路由程序中:
model.model_index=function(currentpage,callback){ var count=3; var offset=(currentpage-1)*count; db.bind('news'); db.news.count({},function(err, len){ if (err) throw err; db.news.find({},{limit: count, skip:offset}).toArray(function(err, items) { if (err) throw err; callback(items,len); db.close(); }); }); };
使用count方法,第一个是查询参数,这里可以不写,其实查询参数很有用的,比如我们要查性别是女的就要加入这个设置,
回调len就是总记录数,我们返回到路由处理:
app.get('/',function(req, res){ var currentpage=req.query.currentpage?req.query.currentpage:1; model.model_index(currentpage,function(items,len){ res.render('index', { title: 'Express',hello: 'hello world!',arr: items,len:len }); }); });
修改index.html模板页面:
<!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <p>Welcome to <%= title %></p> <p><a href="/hello"><%= hello %></a></p> <ul> <% for(var i=0; i<arr.length; i++) {%> <li><a href="/list"><%= arr[i].title %></a><span><%= arr[i].text %></span></li> <% } %> </ul> <h1><%= len %></h1> </body> </html>
查看,显示为10,和总记录相同,下面我们对处理一气呵成:
修改model.js,把总页数,记录内容,总页数,全部返回:
model.model_index=function(currentpage,callback){ var count=3; var offset=(currentpage-1)*count; db.bind('news'); db.news.count({},function(err, len){ if (err) throw err; var allpage=len%count==0?len/count:Math.floor(len/count)+1; db.news.find({},{limit: count, skip:offset}).toArray(function(err, items) { if (err) throw err; callback(items,len,allpage); db.close(); }); }); };
index.js:
app.get('/',function(req, res){ var currentpage=req.query.currentpage?req.query.currentpage:1; model.model_index(currentpage,function(items,len,allpage){ res.render('index', { title: 'Express',hello: 'hello world!',arr: items,len:len,allpage:allpage,cur:currentpage }); }); });
index.html:
<!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <p>Welcome to <%= title %></p> <p><a href="/hello"><%= hello %></a></p> <ul> <% for(var i=0; i<arr.length; i++) {%> <li><a href="/list"><%= arr[i].title %></a><span><%= arr[i].text %></span></li> <% } %> </ul> <div> <% for(var i=1;i<=allpage;i++){ %> <a href="/?currentpage=<%= i %>"><%= i %></a> <% }; %> 总页数:<span><%= allpage %></span> 当前在<span><%= cur %></span>页 共<span><%= len %></span>记录 </div> </body> </html>
我们预览一下:
虽然长得丑,不过也算是比较全了,这只是最最简单分页,在现实上其实还要有很多处理,比如当前页高亮,页数过渡怎么显示,还有上一页,下一页,第一页,最后一页,跳页的处理等,可以自己研究。
总结:
针对数据库的api:
count方法,第一个参数值query,回调返回总页数
find方法,第一个参数query,还可以写高级的skip和limit跳记录和限制处理,和sql语句的select很像skip如同mysql的limit
toArray 转为数组形式,方便输出显示,和mysql的mysql_fetch_toarray很像。
还有一个sort设置,在find方法里,和mysql的排序一样
2.ajax加载更多显示数据
我们还是使用news集合数据做处理,不过采用ajax的形式,针对/hello做处理,在hello.html引入jq类库。
我们把jq类库放在public的javascripts下,
hello.html引用
<!DOCTYPE html> <html> <head> <title>hello</title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <ul> <% for(var i=0; i<arr.length; i++) {%> <li><span><%= arr[i].name %></span></li> <% } %> </ul> </body> <script src="javascripts/jquery-1.10.2.js"></script> </html>
我们会感觉很困惑,hello.html在views下,jq类库在public下,为何引用时直接javascripts/jquery-1.10.2.js就可以了,
不应该是../public/javascripts/jquery-1.10.2.js吗?
我们打开app.js,找到这个部分:
__dirname是node的全局对象,返回app.js的目录,这个方法就是针对静态模板,路径的公用部分是app.js路径/public。
path模块的join是路径拼接方法。
我们已经有了分页的基础,对ajax的分页实现,加快速度:
index.js路由处理:
app.get('/hello', function(req, res){ var currentpage=req.query.currentpage?req.query.currentpage:1; model.model_index(currentpage,function(items){ res.render('hello', { arr: items }); }); });
如果没有参数,显示第一页;
model.js:
model.model_hello=function(currentpage,callback){ var count=3; var offset=(currentpage-1)*count; db.bind('news'); db.news.find({},{limit: count, skip:offset}).toArray(function(err, items) { if (err) throw err; callback(items); db.close(); }); };
返回拿到的的跳页数据;
hello.html先测试显示:
<!DOCTYPE html> <html> <head> <title>hello</title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <ul> <ul> <% for(var i=0; i<arr.length; i++) {%> <li><a href="/list"><%= arr[i].title %></a><span><%= arr[i].text %></span></li> <% } %> </ul> </ul> </body> <script src="javascripts/jquery-1.10.2.js"></script> </html>
hello.html显示了3条记录,我们在页面加一个”加载更多“按钮,然后写ajax请求:
<!DOCTYPE html> <html> <head> <title>hello</title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <ul> <ul id="list"> <% for(var i=0; i<arr.length; i++) {%> <li><a href="/list"><%= arr[i].title %></a><span><%= arr[i].text %></span></li> <% } %> </ul> </ul> <input type="button" id="more" value="加载更多"> </body> <script src="javascripts/jquery-1.10.2.js"></script> <script type="text/javascript"> $(function(){ var more=1; $("#more").click(function(){ more+=1; $.ajax({ url: "/hellomore", type: "GET", data:{more:more}, dataType: "json", error: function(){ alert('Error'); }, success: function(data,status){ for(var i=0;i<data.length;i++){ $("#list").append('<li><a href="/list">'+data[i].title+'</a><span>'+data[i].text+'</span></li>'); }; } }); }); }); </script> </html>
针对ajax我们加入路由处理:
app.get('/hellomore', function(req, res){ model.model_hello(req.query.more,function(items){ res.send(items); }); });
res.send方法就是返回数据,res.render是返回给模板。
预览一下效果:
点击“加载跟多”
我们知道ajax是异步请求,就好像偷偷的去指定地方那东西,然后获取到,在以js插入到标签里,也就无刷新处理了。
我们是发送get请求,每次给页数加1,偷偷拿到返回的数据,插入到ul内部。
总结:
index.js,针对首页和hello做了处理
var formidable = require('formidable'); var fs = require('fs'); var crypto = require('crypto'); var model = require('../model/model'); function rout(app){ app.get('/',function(req, res){ var currentpage=req.query.currentpage?req.query.currentpage:1; model.model_index(currentpage,function(items,len,allpage){ res.render('index', { title: 'Express',hello: 'hello world!',arr: items,len:len,allpage:allpage,cur:currentpage }); }); }); app.get('/hello', function(req, res){ var currentpage=req.query.currentpage?req.query.currentpage:1; model.model_hello(currentpage,function(items){ res.render('hello', { arr: items }); }); }); app.get('/hellomore', function(req, res){ model.model_hello(req.query.more,function(items){ res.send(items); }); }); app.get('/list', function(req, res){ res.render('list', { text: req.query.id }); }); app.get('/login', function(req, res){ res.render('login'); }); app.post('/logincheck', function(req, res){ var user= req.body.user; var pass= req.body.pass; if(user=="tom" && pass=="tom"){ res.redirect('/'); }else{ res.redirect('/login'); }; }); app.get('/file', function(req, res){ res.render('file'); }); app.post('/upfile', function(req, res){ //code var form = new formidable.IncomingForm(); form.uploadDir = "./upload"; form.parse(req, function(err, fields, files) { if (err) { res.redirect('/file'); } var tmp_path, target_path; if (files.file.size > 0) { //表示有文件上传 tmp_path = files.file.path;//内存中的文件,当前文件目录 var picType = files.file.name.split(".")[1];//后缀名 //移动目的目录 target_path = './public/images/pic_1.' + picType; //同步方式移动文件 fs.renameSync(tmp_path, target_path); }else{ res.redirect('/file'); }; }); }); app.get('/fs', function(req, res){ fs.writeFile('./fs/me/1.txt', 'read me','utf8', function (err) { if (err) throw err; }); }); app.get('/crypto', function(req, res){ var pass="admin"; var md5 = crypto.createHash('md5'); var mpass=md5.update(pass).digest('hex'); var rmpass=mpass.substring(2); res.render('crypto', { res:pass,resm:mpass,resrm:rmpass }); }); app.get('/globals', function(req, res){ res.render('globals', { res:__dirname+":"+__filename }); }); }; exports.rout=rout;
model.js加入查询处理等
var config = require('./config'); var mongo = require('mongoskin'); var db = mongo.db(config.connect, {native_parser:true}); var model={}; model.model_index=function(currentpage,callback){ var count=3; var offset=(currentpage-1)*count; db.bind('news'); db.news.count({},function(err, len){ if (err) throw err; var allpage=len%count==0?len/count:Math.floor(len/count)+1; db.news.find({},{limit: count, skip:offset}).toArray(function(err, items) { if (err) throw err; callback(items,len,allpage); db.close(); }); }); }; model.model_hello=function(currentpage,callback){ var count=3; var offset=(currentpage-1)*count; db.bind('news'); db.news.find({},{limit: count, skip:offset}).toArray(function(err, items) { if (err) throw err; callback(items); db.close(); }); }; module.exports=model;
index.html
<!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <p>Welcome to <%= title %></p> <p><a href="/hello"><%= hello %></a></p> <ul> <% for(var i=0; i<arr.length; i++) {%> <li><a href="/list"><%= arr[i].title %></a><span><%= arr[i].text %></span></li> <% } %> </ul> <div> <% for(var i=1;i<=allpage;i++){ %> <a href="/?currentpage=<%= i %>"><%= i %></a> <% }; %> 总页数:<span><%= allpage %></span> 当前在<span><%= cur %></span>页 共<span><%= len %></span>记录 </div> </body> </html>
hello.html ajax请求,注意jq类库的引入
<!DOCTYPE html> <html> <head> <title>hello</title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <ul> <ul id="list"> <% for(var i=0; i<arr.length; i++) {%> <li><a href="/list"><%= arr[i].title %></a><span><%= arr[i].text %></span></li> <% } %> </ul> </ul> <input type="button" id="more" value="加载更多"> </body> <script src="javascripts/jquery-1.10.2.js"></script> <script type="text/javascript"> $(function(){ var more=1; $("#more").click(function(){ more+=1; $.ajax({ url: "/hellomore", type: "GET", data:{more:more}, dataType: "json", error: function(){ alert('Error'); }, success: function(data,status){ for(var i=0;i<data.length;i++){ $("#list").append('<li><a href="/list">'+data[i].title+'</a><span>'+data[i].text+'</span></li>'); }; } }); }); }); </script> </html>