// models/list.js var pool = require('./db'); module.exports = { // 获取首页的主题 getIndexList : function(cb){ pool.getConnection(function(err, connection){ if(err) throw err; // 连表查询,获取到作者的用户名 connection.query('SELECT `list`.*, username FROM `list`, `user` WHERE `list`.`uid`=`user`.`id`', function(err, result){ if(err) throw err; cb(result); connection.release(); // 接下来connection已经无法使用,它已经被返回到连接池中 }) }); } }
在routes中的index.js中调用getIndexList获取数据,并调用index.ejs模板:
// routes/index.js var list_m = require('../models/list'); router.get('https://www.jb51.net/', function(req, res, next) { list_m.getIndexList(function(result){ res.render('index', { data:result }); // 选择index模板并传递数据 }) });
在views/index.ejs创建首页模板:
<h1>列表</h1> <table> <tr> <td>标题</td> <td>作者</td> <td>创建时间</td> </tr> <% for(var i=0, len=data.length; i<len; i++) { %> <tr> <td><a href="/list/<%=data[i].id %>.html" title="<%=data[i].title %>"><%=data[i].title %></a></td> <td><%=data[i].username %></td> <td><%=data[i].createtime %></td> </tr> <% } %> </table> <% if(user.username){ %> <!-- 在登录状态展示输入框 --> <div> <p><input type="text"></p> <textarea cols="100" rows="10"></textarea> <p><input type="button" value="提交"><span></span></p> </div> <% }%>
展示数据完毕。
4.2 发表主题
我们在首页上添加了可以输入标题和内容的两个输入窗口,可以使用ajax的方式提交数据。
<script type="text/javascript" src="https://mat1.gtimg.com/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="'https://www.jb51.net/+result.data.url+'" 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.js router.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.js /* 添加主题 uid, title, content, createtime */ addTopic : 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 // :3000/list/1.html router.get('/:pid.html', function(req, res) { var pid = req.params.pid || 1; console.log(pid); });
在详情页中需要获取到这个主题的详细信息和对这个主题的回复,因此在list_m中: