一、应用生成器
使用上节学习到express的知识,我们也可以从0开始,一步步把系统搭建起来。不过express中还有一个应用生成器,使用这个应用生成器可以快速的创建一个应用的框架,然后我们再在这个框架中完善我们需要的内容。
首先安装应用生成器:
$npm install -g express-generator
运行express --version若能正常输出版本号,则安装成功。
我们的论坛名称可以为node_express_forum,然后使用express创建一个框架:
$express node_express_forum
运行后,生成器会在这个目录下生成几个目录和文件:
create : node_express_forum create : node_express_forum/package.json create : node_express_forum/app.js create : node_express_forum/public create : node_express_forum/public/javascri create : node_express_forum/public/images create : node_express_forum/public/styleshe create : node_express_forum/public/styleshe create : node_express_forum/routes create : node_express_forum/routes/index.js create : node_express_forum/routes/users.js create : node_express_forum/views create : node_express_forum/views/index.jad create : node_express_forum/views/layout.ja create : node_express_forum/views/error.jad create : node_express_forum/bin create : node_express_forum/bin//libs/jquery/1.12.0/jquery.min.js"></script><script type="text/javascript"> var running = false; $('.submit').on('click', function(){ if(running) return; running = true; $('.tip').text(''); var title = $('.add .title').val(); content = $('.add .content').val(); if(!title || !content){ $('.tip').text('*输入不能为空'); return; } $('.tip').text('数据正在提交中...'); $.ajax({ url : '/list/addtopic', // 提交接口 data : {title:title, content:content}, dataType : 'json', type : 'get' }).done(function(result){ if(result.code==0){ var html = '<tr><td><a href="'+result.data.url+'" rel="external nofollow" title="'+result.data.title+'">'+result.data.title+'</a></td><td>'+result.data.author+'</td><td>'+result.data.createtime+'</td></tr>'; $('table').append(html); $('.tip').text(''); $('.title, .content').val(''); }else{ $('.tip').text('添加失败'); } running = false; }) })</script>
这里的提交接口是/list/addtopic,因此我们需要再创建一个这样的路由:在routes目录下创建list.js:
// routes/list.jsrouter.get('/addtopic', function(req, res){ // 在登录状态下可以添加主题 if(req.session.user){ var title = req.query.title, content = req.query.content, uid = req.session.user.uid, createtime = parseInt(Date.now()/1000); var params = {uid:uid, title:title, content:content, createtime:createtime}; list_m.addTopic(params, function(result){ // console.log(result); if(result.affectedRows){ res.json({code:0, msg:'添加成功', data:{url:'/list/'+result.insertId+'.html', title:title, author:req.session.user.username, createtime:createtime}}); }else{ res.json({code:2, msg:'添加失败,请重新尝试'}) } }); }else{ res.json({code:1, msg:'您还未登录'}) }})
这里用到了list_m.addTopic,因此需要在models/list.js中添加 addTopic 方法:
// models/list.jsaddTopic : function(params, cb){ pool.getConnection(function(err, connection){ if(err) throw err; connection.query('INSERT INTO `list` SET ?', params, function(err, result){ if(err) throw err; cb(result); connection.release(); // 接下来connection已经无法使用,它已经被返回到连接池中 }) });}
4.3 详情页
在首页列表中,可以看到,我们将详情页的链接设置为了/list/1.html的方式,也可以设置成其他的方式(比如 /list?pid=1 等),只要设置好路由就行。
// routes/list.js// http://127.0.0.1:3000/list/1.htmlrouter.get('/:pid.html', function(req, res) { var pid = req.params.pid || 1; console.log(pid);});
在详情页中需要获取到这个主题的详细信息和对这个主题的回复,因此在list_m中:
// models/list.js// 根据id查询主题的详情信息getListById : function(id, cb){ pool.getConnection(function(err, connection){ if(err) throw err; connection.query('SELECT * FROM `list` WHERE `id`=?', [id], function(err, result){ if(err) throw err; cb(result); connection.release(); // 接下来connection已经无法使用,它已经被返回到连接池中 }) });},// 某主题的回复getReplyById : function(pid, cb){ pool.getConnection(function(err, connection){ if(err) throw err; connection.query('SELECT * FROM `reply` WHERE `pid`=?', [pid], function(err, result){ if(err) throw err; cb(result); connection.release(); // 接下来connection已经无法使用,它已经被返回到连接池中 }) });}
然后在路由中进行调用,这里使用async简单的控制了下两个异步的流程问题:
// http://127.0.0.1:3000/list/1.htmlrouter.get('/:pid.html', function(req, res) { var pid = req.params.pid || 1; async.parallel([ function(callback){ list_m.getListById(pid, function(result){ callback(null, result[0]); }) }, function(callback){ list_m.getReplyById(pid, function(result){ callback(null, result); }) }, ], function(err, results){ // console.log( results ); // res.json(results); res.render('list', { data:results }); }) });
稍微解释下async.parallel的功能,下节我们会详细的讲解。 async.parallel([f1, f2, f3,…, fn], fb); 是f1到fn所有的异步都执行完了就会执行fb函数。这里我们是主题的详情和对主题的回复都请求完成了,就可以调用模板渲染。
// views/list.ejs<p><a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" >返回到首页</a></p><h1>详情</h1><p>标题: <%=data[0].title %></p><div><%=data[0].content %></div><div class="reply"> <h2>评论</h2> <div class="reply_con"> <table> <% for(var i=0, len=data[1].length; i<len; i++) { %> <tr> <td><%=(i+1) %></td> <td><%=data[1][i].content %></td> <td><%=data[1][i].createtime %></td> </tr> <% } %> </table> </div></div>
对主题的回复功能可以自己实现一下。
总结
写着写着就发现篇幅这么大了,而且充斥了大量的代码,需要我们细心的理解。下面给出详细的示例代码,大家可以下载学习,希望本文的内容对大家能有所帮助。
下载地址:点击这里