以前使用 WordPress 的时候,每次自己写主题总要加上一个功能:相关文章。总感觉用户看完文章后可能会想看看还有什么相关的文章,以便更加全面的了解这个问题。转到 Hexo 后,对 Hexo 的代码进行了一点研究,也摸索着写了一个主题,今天花了一个下午的时间,为自己 Hexo 博客加上了相关文章功能。
相关文章的实现方式大概可以分为两个大类:一是使用第三方服务,例如无觅、友荐、bShare、阿里云的云推荐以及百度推荐等。这种方式的优点是对相关文章的分析可能更强大,在如何定义文章是否相关上可能更加全面,缺点是需要引入较多的外站 js 文件等。第二类是自己写代码实现。现在网上对 Hexo 的相关文章实现第一类的文章非常多,而我更倾向于使用第二种方法,于是下午自己代码实现了 Hexo 的相关文章功能。
首先说一下 Hexo 实现相关文章的原理。我实现的是基于 tag 相关的相关文章,也就是说两篇文章重合的 tag 数量越多则认为这两篇文章越相关。这个原理虽然比较简单,但我觉得对于个人博客来说,只要 tag 管理设置得当,也够用了。
实现代码如下:
hexo.extend.helper.register('related_posts', function(currentPost, allPosts){
var relatedPosts = [];
currentPost.tags.forEach(function (tag) {
allPosts.forEach(function (post) {
if (isTagRelated(tag.name, post.tags)) {
var relatedPost = {
title: post.title,
path: post.path,
weight: 1
};
var index = findItem(relatedPosts, 'path', post.path);
if (index != -1) {
relatedPosts[index].weight += 1;
} else{
if (currentPost.path != post.path) {
relatedPosts.push(relatedPost);
};
};
};
});
});
if (relatedPosts.length == 0) {return ''};
var result = '<h3>相关文章:</h3><ul class="related-posts">';
relatedPosts = relatedPosts.sort(compare('weight'));
for (var i = 0; i < Math.min(relatedPosts.length, 10); i++) {
result += '<li><a href="/' + relatedPosts[i].path + '">' + relatedPosts[i].title + '</a></li>';
};
result += '</ul>';
// console.log(relatedPosts);
return result;
});
function isTagRelated (tagName, TBDtags) {
var result = false;
TBDtags.forEach(function (tag) {
if (tagName == tag.name) {
result = true;
};
})
return result;
}
function findItem (arrayToSearch, attr, val) {
for (var i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i][attr] == val) {
return i
};
};
return -1;
}
function compare (attr) {
return function (a, b) {
var val1 = a[attr];
var val2 = b[attr];
return val2 - val1;
}
}
使用方法很简单,在自己主题文件夹下的 script 文件夹中建立一个 related_post.js 的文件,然后将上面代码拷入,再到需要调用相关文章的页面模板中添加 <%- related_posts(post, site.posts) %> 即可。注意传入的两个参数分别为当前文章和网站的所有文章。最后,再稍微调整下样式即可。
一般来说,添加的位置为主题模板 post 中,以 ejs 模板为例,则为主题目录下的 layout/post.ejs 文件,在最后添加以下代码即可:
<%- related_posts(post, site.posts) %>
写代码和写文章都不容易,我最近搜了一下自己以前写的文章,发现很多被转载也不留原文作者和链接,总之,愿意转载的朋友希望你能以链接形式注明本文地址。