Plume主题增强之首页增加最近更新模块
介绍
在首页展示最近一年内更新或创建的文章列表(最多 5 篇),以横条形式并排展示。
- 每条显示文章标题(超长自动截断,悬停时 tooltip 显示完整标题)和相对时间
- 时间取
updateTime和createTime中较晚的一个 - 时间显示格式:7 天内显示"今天 / 昨天 / N 天前",超过 7 天显示"月-日"
- 条目之间用
|分隔,移动端自动改为纵向堆叠
效果预览

项目结构总览
docs/
├── index.md ← 修改:添加 <RecentUpdates /> 标签
└── .vuepress/
├── components/
│ └── RecentUpdates.vue ← 新增:最近更新组件
├── config.ts ← 修改:在 extendsPage 中注入 createTime、updateTime 到路由元数据
└── client.ts ← 修改:注册 RecentUpdates 为全局组件| 文件 | 操作 | 说明 |
|---|---|---|
docs/.vuepress/components/RecentUpdates.vue | 新增 | 最近更新横条组件,包含逻辑与样式 |
docs/.vuepress/config.ts | 修改 | 在 extendsPage 中将 createTime、updateTime 注入路由元数据 |
docs/.vuepress/client.ts | 修改 | 通过 app.component 注册 RecentUpdates 为全局组件 |
docs/index.md | 修改 | 在首页内容中添加 <RecentUpdates /> 标签 |
实现过程
1. 时间取最晚值
文章的「最近更新」时间应优先取 updateTime(手动编辑时间),若不存在或早于 createTime,则回退到 createTime。这样能保证显示的始终是最后一次有意义的变更时间:
const createTime = route.meta.createTime
const updateTime = route.meta.updateTime
let finalTime = createTime
if (updateTime) {
const isNewer = new Date(updateTime) > new Date(createTime)
if (isNewer) finalTime = updateTime
}2. 一年时间窗口过滤
组件只展示最近一年内活跃的文章,避免首页显示几年前的旧内容:
const oneYearAgo = new Date()
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1)
const oneYearAgoTime = oneYearAgo.getTime()
// 在遍历路由时过滤掉超出时间窗口的页面
if (new Date(finalTime).getTime() < oneYearAgoTime) return3. 排除特殊页面
博客列表页、归档页、标签页等系统页面不应出现在「最近更新」中,通过路径匹配过滤:
const EXCLUDED = ['/', '/blog/', '/blog/tags/', '/blog/archives/', '/blog/categories/']
if (path.includes('/404') || EXCLUDED.includes(path)) return同时与 LatestPosts 的处理方式相同,异步加载 frontmatter 排除 isCatalogPage 为 true 的目录页。
4. 取前 5 条并排序
recentPosts computed 属性完成所有过滤和排序后,取时间最新的前 5 篇:
const recentPosts = computed(() => {
return allPages
.sort((a, b) => new Date(b.createTime) - new Date(a.createTime))
.slice(0, 5)
})5. 横条布局与间距消除
模块在首页中通过 Plume 的 type: custom 区块嵌入,该区块默认有内边距。使用全局 CSS 的 :has() 选择器检测到内部有 .recent-updates 时将内边距归零,避免出现多余空白:
.vp-home-box:has(.recent-updates) {
padding-top: 0 !important;
}6. 悬停显示完整标题
标题过长时以省略号截断,但用户无法得知完整内容。通过在 <span> 上绑定原生 title 属性,鼠标悬停时浏览器自动弹出 tooltip 显示完整标题,无需任何额外 JS 或自定义弹窗:
<span class="update-title" :title="post.title">{{ post.title }}</span>使用方法
第一步:修改 config.ts
在 docs/.vuepress/config.ts 的 extendsPage 中确保包含 createTime 和 updateTime 字段:
export default defineUserConfig({
extendsPage: (page) => {
page.routeMeta = {
title: page.title,
createTime: page.frontmatter.createTime,
updateTime: page.frontmatter.updateTime,
}
},
})第二步:新增组件文件
将 RecentUpdates.vue 创建到 docs/.vuepress/components/ 目录下。
第三步:修改 client.ts
在 docs/.vuepress/client.ts 中注册全局组件:
import { defineClientConfig } from 'vuepress/client'
import RecentUpdates from './components/RecentUpdates.vue'
export default defineClientConfig({
enhance({ app }) {
app.component('RecentUpdates', RecentUpdates)
},
})第四步:修改 docs/index.md
在首页 docs/index.md 中添加组件标签(放在 frontmatter 下方的 Markdown 内容区域):
<RecentUpdates />