上一節已經實現了登陸、註冊、發表文章和文章讀取的功能,今天咱加上評論、文章頁面和做者頁面。javascript
評論只能在進入文章頁面後才能進行,因此我們先寫文章頁面。css
在上一節的代碼中,我已經給文章標題添加了超連接了,html
<a href="/<%= post.user %>/<%= post.time.day%>/<%= post.title %>"><%= post.title %></a>
根據這個連接地址,進入文章頁面的路由控制就能夠寫成這樣:java
app.get('/:user/:time/:title', function(req,res){ User.get(req.params.user,function(err, user){ Post.getOne(req.params.user, req.params.time, req.params.title, function(err, post){//還記得post.js裏面獲取文章的函數吧? if(err){ req.flash('err',err); return res.redirect('/'); } res.render('article',{ title: req.params.title, post: post, user: req.session.user, success: req.flash('success').toString(), error: req.flash('error').toString() }); }); }); });
接下來寫文章頁面的視圖 article.ejsweb
<%- include header %> <p><h2><a href="/<%= locals.post.user %>/<%= locals.post.time.day %>/<%= locals.post.title %>"><%= locals.post.title %></a></h2></p> <p class="info"> 做者:<a href="/<%= locals.post.user %>"><%= locals.post.user %></a> | 日期:<%= locals.post.time.minute %> </p> <p><%- locals.post.post %></p> <p class="info">閱讀:<%= locals.post.pv %> | 評論:<%= locals.post.comments.length %> <%- include footer %>
進入主頁點擊文章標題看看效果吧?正則表達式
發現問題了吧?樣式都沒有了,緣由先不說,說完解決方法以後你就明白了:數據庫
把header.ejs中引入style.css的路徑寫成這樣:session
<link rel="stylesheet" href="/stylesheets/style.css">
好了,ok了!數據結構
如今在文章頁面後面加上評論,完整的article.ejs爲:app
<%- include header %> <p><h2><a href="/<%= locals.post.user %>/<%= locals.post.time.day %>/<%= locals.post.title %>"><%= locals.post.title %></a></h2></p> <p class="info"> 做者:<a href="/<%= locals.post.user %>"><%= locals.post.user %></a> | 日期:<%= locals.post.time.minute %> </p> <p><%- locals.post.post %></p> <p class="info">閱讀:<%= locals.post.pv %> | 評論:<%= locals.post.comments.length %> <br /><br /> <% if(locals.post.comments){ %> <% locals.post.comments.forEach(function(comment, index){ %> <p><a href="/<%= comment.website %>"><%= comment.name %></a> <time>回覆於 <%= comment.time %></time></p> <p><%- comment.content %></p> <% }) %> <% } %> <form method="post"> <% if(!locals.user){ %> 姓名:<input type="text" name="name" /><br /> 郵箱:<input type="text" name="email" /><br /> 網址:<input type="text" name="website" /><br /> <% } %> 留言:<br /><textarea name="content" rows="5" cols="80"></textarea> <br /><input type="submit" value="留言" /> </form> <%- include footer %>
評論視圖有了,下面就是處理過程了,在app.get("/:user/:time/:title",function(){})後面添加:
app.post('/:user/:time/:title', function(req,res){ var comment = null, date = new Date(), time = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes(); if(req.session.user){ var name=req.session.user.name; comment = {"name":name, "email":name+"@gmail.com", "website":"www."+name+".com", "time":time, "content":req.body.content} } else { comment = {"name":req.body.name, "email":req.body.email, "website":req.body.website, "time":time, "content":req.body.content} } var oneComment = new Comment(req.params.user, req.params.time, req.params.title, comment); oneComment.save(function(err){ if(err){ req.flash('error', err); return res.redirect('/'); } req.flash('success', '評論成功!'); res.redirect('back');//這句話的做用是評論成功後返回到被評論文章 }); });
做者頁面和文章頁面是相似的,點擊做者名字,顯示該做者的全部文章。
做者頁面路由控制:
app.get('/:user', function(req,res){ User.get(req.params.user, function(err, user){ if(!user){ return res.redirect('/'); } Post.getAll(req.params.user, function(err, posts){ if(err){ req.flash('err',err); return res.redirect('/'); } res.render('user',{ title: req.params.user, posts: posts, user: req.session.user, success: req.flash('success').toString(), error: req.flash('error').toString() }); }); }); });
做者頁面視圖user.ejs:
<%- include header %> <% locals.posts.forEach(function(post, index){ %> <p><h2><a href="/<%=post.user %>/<%=post.time.day %>/<%=post.title %>"><%= post.title %></a></h2> <p class="info"> 做者:<a href="/<%= post.user %>"><%= post.user %></a> | 日期:<%= post.time.minute %> </p> <p><%- post.post %></p> <p class="info">閱讀:<%= post.pv %> | 評論:<%= post.comments.length %></p> <% }) %> <%- include footer %>
到目前爲止,博客系統已經完成了。還有個地方能夠完善一下。如今沒有作權限控制,無論登陸仍是未登陸均可以訪問頁面。稍稍修改一下,未登陸用戶不能夠進入文章頁面和做者頁面、不能夠評論、不能夠發佈文章、不能夠退出,當用戶試圖執行以上操做的時候,均跳轉到登陸頁面。
我們在index.js中寫一個函數檢驗用戶是否登陸:
function checkLogin(req, res, next){ if(!req.session.user){ req.flash('error','請登陸'); return res.redirect('/login'); } next(); }
而後在上面提到的幾個路由控制前面加上checkLogin,如在app.get("/logout",function(){});以前加上:app.get('/logout',checkLogin);
對於登陸操做,應該只對未登陸用戶開放,因此添加一個函數校驗是否未登陸:
function checkNotLogin(req,res,next){ if(req.session.user){ req.flash('error','已登陸'); return res.redirect('/'); } next(); }
而後在login對應的get和post處理前分別添加app.get('/login',checkNotLogin); 和app.post('/login',checkNotLogin);
好了,到如今爲止,粗糙的博客系統算是作好了,像csdn的標籤功能其實和文章頁面差很少,就不寫了。
有幾個問題作一下小說明,也是我本身在第一次開發的過程當中遇到的:
一、路由控制問題。要保證彼此的路由不會相互干擾,好比說,logout不會被做者頁面的路由攔截,路由的書寫順序就很重要了。你能夠試試把logou路由控制t放在user以後。因此在涉及到正則表達式類型的路由控制的時候,請認真思考路由的書寫順序,當你的路由解析出乎意料的時候,記得調整路由順序。
二、前面已經說過的樣式問題。我第一次開發的時候,參考的是別人給出的解決方案,就是在article.ejs裏面在引入一遍style.css,後來總以爲那樣不合理,才找出瞭解決方案。因此引入public下的文件的時候,建議用根目錄。
三、我寫的這個從一開始到最後,數據結構都沒有變過,省了不少。可是真正作開發的時候,不必定會那麼順利。好比我剛開始作的時候,每加一個功能就要修改一次數據結構,而後就會出現先前存進去的數據包含了後面才定義的屬性,出現undefined。這時候也不用着急,先清空數據庫,基本上就沒問題了,還有問題的話,本身看控制檯的錯誤提示,基本上也能夠本身解決了。
四、最後,題外話,寫程序,思路要儘可能清晰一些,開始着手書寫代碼的時候,要細心,我的以爲寫代碼能夠遵循增量開發的原則,先搭好架子,後期再一步步擴展,一步步測試,這樣便於調試。