Node.js 博客实例(九)标签和标签页面
原教程 https://github.com/nswbmw/N-blog/wiki/_pages的第九章。因为版本号等的原因。在原教程基础上稍加修改就可以实现。
每篇文章最多有三个标签(少于三个也能够),当点击主页左側标签页链接时,跳转到标签页并列出全部已存在标签;当点击随意一个标签链接时,跳转到该标签页并列出全部含有该标签的文章。
首先我们来实现给文章加入标签的功能。
打开 post.ejs ,在 <input type="text" name="title" /><br /> 后加入:
<input type="text" name="tag1" /><input type="text" name="tag2" /><input type="text" name="tag3" /><br />打开 index.js ,将 app.post('/post') 内的:
var currentUser = req.session.user, post = new Post(currentUser.name, req.body.title, req.body.post);改动为:
var currentUser = req.session.user,
tags = [req.body.tag1, req.body.tag2, req.body.tag3],
post = new Post(currentUser.name, req.body.title, tags, req.body.post);
打开 post.js 。将:
function Post(name, title, post) { this.name = name; this.title= title; this.post = post; }改动为:
function Post(name, title, tags, post) { this.name = name; this.title = title; this.tags = tags; this.post = post; }将:
var post = { name: this.name, time: time, title: this.title, post: this.post, comments: [] };改动为:
var post = { name: this.name, time: time, title: this.title, tags: this.tags, post: this.post, comments: [] };如今我们就能够在发表文章的时候加入标签了。
接下来我们改动 index.ejs 、 user.ejs 和 article.ejs 来显示文章的标签。
改动 index.ejs 、 user.ejs 和 article.ejs,将:
<p class="info"> 作者:<a href="/u/<%= post.name %>"><%= post.name %></a> | 日期:<%= post.time.minute %> </p>改动为:
<p class="info"> 作者:<a href="/u/<%= post.name %>"><%= post.name %></a> | 日期:<%= post.time.minute %> | 标签: <% post.tags.forEach(function (tag, index) { %> <% if (tag) { %> <a class="tag" href="/tags/<%= tag %>"><%= tag %></a> <% } %> <% }) %> </p>最后,在 style.css 中加入例如以下样式:
.tag{background-color:#ff0000;border-radius:3px;font-size:14px;color:#ffffff;display:inline-block;padding:0 5px;margin-bottom:8px;} .tag:hover{text-decoration:none;background-color:#ffffff;color:#000000;-webkit-transition:color .2s linear;}至此,我们给博客加入了标签功能。
接下来我们给博客添加标签页。
改动 header.ejs ,在 <span><a title="存档" href="/archive">archive</a></span> 下一行加入:
<span><a title="标签" href="/tags">tags</a></span>改动 index.js ,在 app.get('/archive') 后加入例如以下代码:
app.get('/tags', function (req, res) { Post.getTags(function (err, posts) { if (err) { req.flash('error', err); return res.redirect('/'); } res.render('tags', { title: '标签', posts: posts, user: req.session.user, success: req.flash('success').toString(), error: req.flash('error').toString() }); }); }); app.get('/tags/:tag', function (req, res) { Post.getTag(req.params.tag, function (err, posts) { if (err) { req.flash('error',err); return res.redirect('/'); } res.render('tag', { title: 'TAG:' + req.params.tag, posts: posts, user: req.session.user, success: req.flash('success').toString(), error: req.flash('error').toString() }); }); });打开 post.js 。在最后加入:
//返回全部标签 Post.getTags = function(callback) { mongodb.open(function (err, db) { if (err) { return callback(err); } db.collection('posts', function (err, collection) { if (err) { mongodb.close(); return callback(err); } //distinct 用来找出给定键的全部不同值 collection.distinct("tags", function (err, docs) { mongodb.close(); if (err) { return callback(err); } callback(null, docs); }); }); }); }; //返回含有特定标签的全部文章 Post.getTag = function(tag, callback) { mongodb.open(function (err, db) { if (err) { return callback(err); } db.collection('posts', function (err, collection) { if (err) { mongodb.close(); return callback(err); } //查询全部 tags 数组内包括 tag 的文档 //并返回仅仅含有 name、time、title 组成的数组 collection.find({ "tags": tag }, { "name": 1, "time": 1, "title": 1 }).sort({ time: -1 }).toArray(function (err, docs) { mongodb.close(); if (err) { return callback(err); } callback(null, docs); }); }); }); };注意:这里我们用了 distinct (详见《mongodb权威指南》)返回 tags 键的全部不同值,由于有时候我们发表文章的标签是一样的。所以这样避免了获取反复的标签。
在 blog/views /目录下新建 tags.ejs 。加入例如以下代码:
<%- include header %> <% posts.forEach(function (tag, index) { %> <a class="tag" href="/tags/<%= tag %>"><%= tag %></a> <% }) %> <%- include footer %>在 blog/views /目录下新建 tag.ejs ,加入例如以下代码:
<%- include header %> <ul class="archive"> <% var lastYear = 0 %> <% posts.forEach(function (post, index) { %> <% if (lastYear != post.time.year) { %> <li><h3><%= post.time.year %></h3></li> <% lastYear = post.time.year } %> <li><time><%= post.time.day %></time></li> <li><a href="/u/<%= post.name %>/<%= post.time.day %>/<%= post.title %>"><%= post.title %></a></li> <% }) %> </ul> <%- include footer %>为了保持和 post.ejs 一致。将 edit.ejs 改动为:
<%- include header %> <form method="post"> 标题:<br /> <input type="text" name="title" value="<%= post.title %>" disabled="disabled" /><br /> 标签:<br /> <input type="text" name="tag1" value="<%= post.tags[0] %>" disabled="disabled" /> <input type="text" name="tag2" value="<%= post.tags[1] %>" disabled="disabled" /> <input type="text" name="tag3" value="<%= post.tags[2] %>" disabled="disabled" /><br /> 正文:<br /> <textarea name="post" rows="20" cols="100"><%= post.post %></textarea><br /> <input type="submit" value="保存改动" /> </form> <%- include footer %>看看效果。发表文章的界面对了标签模块。
我们来发表几篇文章測试一下。
点击左側的标签。可显示出全部标签,点击当中一个标签。则列出全部含有该标签的文章:
点击 t1