如何简化JavaScript时间差代码并解决Jekyll多帖子批量渲染问题
搞定Jekyll多帖子自动渲染时间差的小技巧
我之前也碰到过类似的麻烦——写了个计算时间差的JS函数,结果每个帖子都要手动写JS代码才能渲染,还要在Front-matter里加一堆自定义ID,简直太折腾了。后来摸索出一套简化方案,不用再手动折腾ID,还能自动给所有帖子渲染“X小时前”这种格式,给你分享一下:
第一步:砍掉Front-matter里的冗余配置
之前你在每个帖子里写postedago和postedon完全没必要,Jekyll自带的变量就能帮我们生成唯一标识。直接把Front-matter简化成这样就行:
--- date: 2018-1-4 02:00:00 +0100 ---
省得每次发新帖都要手动加那两个ID字段,省心不少。
第二步:统一帖子时间的HTML结构
把帖子模板里的<time>标签改成用class和自定义数据属性的结构,让JS能批量识别和处理:
<time class="post-time" datetime="{{ post.date | date_to_xmlschema }}" data-post-date="{{ post.date | date_to_rfc822 }}"> <span class="time-ago"></span> </time>
这里用class="post-time"代替原来的ID,方便JS批量获取所有时间元素;data-post-date用来存储帖子的原始发布日期,这样JS不用依赖ID就能拿到日期数据。
第三步:重构JS实现自动批量渲染
你的ago()函数逻辑没问题,我们只需要加个初始化函数,让页面加载完成后自动遍历所有帖子的时间元素,批量渲染时间差:
// 保留你原来的时间差计算函数 function ago(date) { function render(n, unit) { return n + " " + unit + ((n == 1) ? "" : "s") + " ago"; } var seconds = Math.floor((new Date() - date) / 1000); var interval = Math.floor(seconds / (60 * 60 * 24 * 30 * 365)); if (interval >= 1) { return render(interval, "year"); } interval = Math.floor(seconds / (60 * 60 * 24 * 30)); if (interval >= 1) { return render(interval, "month"); } interval = Math.floor(seconds / (60 * 60 * 24)); if (interval >= 1) { return render(interval, "day"); } interval = Math.floor(seconds / (60 * 60)); if (interval >= 1) { return render(interval, "hour"); } interval = Math.floor(seconds / 60); if (interval >= 1) { return render(interval, "minute"); } interval = Math.floor(seconds); return render(interval, "second"); } // 新增自动初始化函数,批量处理所有帖子的时间 function initTimeAgo() { // 获取所有帖子的时间元素 const timeElements = document.querySelectorAll('.post-time'); timeElements.forEach(el => { // 从data属性里读取发布日期,转换成Date对象 const postDate = new Date(el.dataset.postDate); // 找到要渲染时间差的span元素 const timeAgoSpan = el.querySelector('.time-ago'); if (timeAgoSpan) { timeAgoSpan.textContent = ago(postDate); } }); } // 页面加载完成后自动执行初始化 document.addEventListener('DOMContentLoaded', initTimeAgo);
这样一来,不管你有多少帖子,页面加载后都会自动渲染时间差,再也不用给每个帖子写单独的JS代码了。
可选优化:让时间差实时更新
如果想要时间差能自动刷新(比如过了一小时自动从“1小时前”变成“2小时前”),可以加个定时器,每隔一分钟更新一次:
// 新增更新函数 function updateTimeAgo() { const timeElements = document.querySelectorAll('.post-time'); timeElements.forEach(el => { const postDate = new Date(el.dataset.postDate); const timeAgoSpan = el.querySelector('.time-ago'); if (timeAgoSpan) { timeAgoSpan.textContent = ago(postDate); } }); } // 页面加载时初始化,之后每隔60秒更新一次 document.addEventListener('DOMContentLoaded', () => { initTimeAgo(); setInterval(updateTimeAgo, 60000); // 60秒刷新一次 });
内容的提问来源于stack exchange,提问作者Fraktar
相关产品推荐
相关产品推荐

