一、背景
最近新上了“天工 ”模块,打算分享下个人见到的一些好玩的物件(Ps:第一个发布的就是上周在WAIC展会上看到的无人做饭灶 )。顺便也分享下第一次开发带分页的模板 开发经验。
“天工”一词取于明代著作《天工开物》,它是世界上第一部关于农业和手工业生产的综合性著作,记载了明朝中叶以前中国古代的各项技术,被外国学者称它为“中国17世纪的工艺百科全书”。
在过去的“造物”、“收藏”、“足迹”等板块,因为其自身内容较少,导致单页面已经足够满足使用场景。而“天工”版块随着时间推移,分享的物件也会越来越多,于是就需要提前准备好分页功能 。
在官网的API文档中,关于生成器 (Generator) 模块的文档中有提到以下内容:
有分页的归档页面 您可以通过 hexo-pagination 这个方便的官方工具来轻松建立分页归档。
hexo-pagination
就是我们创建多分页模板的核心,下面是官方提供的归档模块(archive)示例代码:
1 2 3 4 5 6 7 8 9 10 var pagination = require ("hexo-pagination" );hexo.extend .generator .register ("archive" , function (locals ) { return pagination ("archives" , locals.posts , { perPage : 10 , layout : ["archive" , "index" ], data : {}, }); });
可以看到生成功能主要是由pagination 提供,它接受三个参数:
“archives”:代表生成目录的路径,此处代表生成的路径就是/archives/***
locals.posts:分页的数据来源。locals是hexo的内部变量,类似于模板内的site变量。通过locals.posts可以获取到全部的文章内容。
{ xxx: xxx }:自定义配置项,主要由以下几个选项构成。
perPage:分页量,此处代表每10条分一页。
layout:生成页面时采用哪个模板。该变量接收String和Array两种值。String代表指定某个模板文件,Array代表优先使用哪个,当第一个不存在则沿用下一个。
data:代表额外赋予到模板page对象变量上的其他属性。
format:默认值为page/%d/
,代表生成的URL为/archives/page/1/
等形式。
三、开始编码 (1)编辑数据源 顾名思义即数据项来源,目前在Hexo中有2种数据源形式:md文件 或者json数据文件 。
md文件 可以通过tag关联或者category关联的形式把多个md文件内容聚合到模板页面上,例如下方示例:
1 2 3 4 5 let tag = site.tags .findOne ({name : '自定义tag名称' })tag.posts .map (...)
json数据文件 是我用的比较多的一类,目前网站的几个拓展模块基本都是采用json文件来实现的数据维护更新。在source/_data
目录下创建的.json
数据文件都可以在模板中通过site.data.xxx
来获取。
在这里我仍然沿用json数据文件 的方式来编写“天工”模块,创建一个名为goods.json
的数据文件。json内容如下:
1 2 3 4 5 6 7 8 9 10 [ { "poster" : "poster.jpg" , "title" : "第一个天工产品" , "description" : "这里是一行简短的产品特点介绍" , "score" : "5" , "price" : "¥2024" , "link" : "/article/waic-2024.html" } ]
(2)创建模板 在模板文件夹下创建一个名为goods.ejs
的模板(此处沿用了hexo默认的ejs模板,其他模板引擎需要调整为对应写法)。
下面是简版的模板代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <% page.posts.map(function(post, i){ %> <p > 封面:<%= post.poster %></p > <p > 标题:<%= post.title %></p > <p > 描述:<%= post.description %></p > <p > 评分:<%= post.score %></p > <p > 价格:<%= post.price %></p > <p > 访问链接:<%= post.link %></p > <% }) %> <% if (page.total > 1){ %> <%- paginator({ escape: false, mid_size: 1 }) %> <% } %>
(3)创建脚本 在scripts
目录下创建生成脚本,命名为generator-goods.js
,内容如下:
1 2 3 4 5 6 7 8 9 10 const pagination = require ("hexo-pagination" );hexo.extend .generator .register ("goods" , function (locals ) { return pagination ("/goods" , locals.data .goods , { perPage : 10 , current : 1 , format : "page/%d/" , layout : "goods.ejs" , }); });
接着运行hexo server
预览就能看到展示效果了。
四、功能优化 (1)菜单栏的选中效果失效 之前菜单栏的自定义页面 可以通过is_page() && page.layout==="xxx"
来匹配和实现当前菜单高亮效果,而通过hexo-pagination
生成的页面is_page()结果为false,且page.layout为undefined 。
解决方法是调整generator-goods.js
脚本内容,在pagination
函数的data变量中补充layout属性信息,之后就可以通过page.layout === "goods"
来匹配页面了。
1 2 3 4 5 6 7 8 9 10 11 12 13 const pagination = require ("hexo-pagination" );hexo.extend .generator .register ("goods" , function (locals ) { return pagination ("/goods" , locals.data .goods , { perPage : 10 , current : 1 , format : "page/%d/" , layout : "goods.ejs" , data : { layout : 'goods' }, }); });
(2)SEO信息优化 在md文件中,可以通过Front-matter
来设置title和description,然后在模板中使用page.title
和page.description
来获取对应信息,例如:
1 2 3 4 5 6 --- title: Hello World description: This is a md file --- 内容...
解决方法还是调整generator-goods.js
,在data中补充对应的属性信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const pagination = require ("hexo-pagination" );hexo.extend .generator .register ("goods" , function (locals ) { return pagination ("/goods" , locals.data .goods , { perPage : 10 , current : 1 , format : "page/%d/" , layout : "goods.ejs" , data : { layout : 'goods' , title : 'Hello World' , description : 'This is a md file' , }, }); });