Plume主题增强之导航栏微信图标悬停展示二维码
介绍
为导航栏中的微信社交图标添加鼠标悬停弹出层,展示微信公众号二维码图片和公众号名称。纯 CSS :hover 实现显示/隐藏,无需额外 JS 事件绑定。
效果预览

项目结构总览
docs/
└── .vuepress/
├── components/
│ └── WechatHover.vue ← 新增:微信悬停二维码组件
├── plume.config.ts ← 修改:添加 wechat 社交图标配置
└── client.ts ← 修改:注册 WechatHover 到 rootComponents| 文件 | 操作 | 说明 |
|---|---|---|
docs/.vuepress/components/WechatHover.vue | 新增 | 微信悬停二维码组件,包含逻辑与样式 |
docs/.vuepress/plume.config.ts | 修改 | 添加 wechat 社交链接,并在 navbarSocialInclude 中声明 |
docs/.vuepress/client.ts | 修改 | 将 WechatHover 添加到 rootComponents |
实现过程
1. 为什么用 MutationObserver 而不是 onMounted 直接查询
导航栏是 Plume 主题的全局布局组件,在 SPA 路由切换时不会销毁重建,但其内部 DOM 节点的渲染时机不确定。如果在 onMounted 中立刻查询 .vp-social-link[aria-label="wechat"],可能尚未渲染到 DOM 里。
解决方案是用一个 50ms 的延迟首次尝试,同时启动 MutationObserver 持续监听,一旦目标节点出现就完成注入,并打上标记防止重复处理:
const ensureWechatHover = () => {
const el = document.querySelector('.vp-social-link[aria-label="wechat"]')
if (!el) return // 节点还没出现,等 MutationObserver 下次触发
if (el.dataset.hoverInit === '1') return // 已处理,跳过
// 动态创建弹出层容器并注入
const container = document.createElement('div')
container.className = 'wechat-hover-content'
container.innerHTML = `
<div class="wechat-qr-wrap">
<img src="${qrCodeSrc}" alt="微信二维码" class="wechat-qr-img" />
<div class="wechat-qr-text">公众号名称: <strong>${accountName}</strong></div>
</div>
`
el.appendChild(container)
el.dataset.hoverInit = '1' // 标记已处理
}
setTimeout(ensureWechatHover, 60) // 延迟首次尝试
mo = new MutationObserver(ensureWechatHover)
mo.observe(document.body, { childList: true, subtree: true })2. 纯 CSS 实现悬停显示
弹出层默认 display: none,只需借助 CSS :hover 伪类即可实现悬停显示,完全不需要 JS mouseenter/mouseleave 事件:
/* 父元素相对定位,为弹出层提供定位基准 */
.vp-social-link[aria-label="wechat"] {
position: relative;
}
/* 弹出层默认隐藏 */
.vp-social-link[aria-label="wechat"] .wechat-hover-content {
display: none;
position: absolute;
left: 50%;
transform: translateX(-50%); /* 水平居中对齐图标 */
top: calc(100% + 8px); /* 出现在图标正下方,留 8px 间距 */
z-index: 9999;
}
/* 悬停时显示 */
.vp-social-link[aria-label="wechat"]:hover .wechat-hover-content {
display: block;
}3. 深色模式适配
Plume 主题切换深色模式时会在 <html> 上添加 data-theme="dark" 属性,通过属性选择器为弹出层覆盖背景色和阴影:
html[data-theme="dark"] .vp-social-link[aria-label="wechat"] .wechat-hover-content {
background: #141414;
color: #ddd;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.6);
}使用方法
第一步:准备二维码图片
将微信公众号二维码图片放入 docs/public/ 目录,例如命名为 wechat-qrcode.jpg。
第二步:修改 plume.config.ts
在 docs/.vuepress/plume.config.ts 中添加微信社交链接配置:
export default defineThemeConfig({
social: [
{ icon: 'wechat', link: '' },
],
navbarSocialInclude: ['wechat', 'github'],
})第三步:新增组件文件
将 WechatHover.vue 创建到 docs/.vuepress/components/ 目录下。
打开组件,修改顶部配置项:
// ===== 配置项 =====
const qrCodeSrc = '/wechat-qrcode.jpg' // 二维码图片路径(相对于 docs/public/)
const accountName = '你的公众号名称' // 公众号名称
// =================第四步:修改 client.ts
在 docs/.vuepress/client.ts 中添加以下配置:
import { defineClientConfig } from 'vuepress/client'
import WechatHover from './components/WechatHover.vue'
export default defineClientConfig({
rootComponents: [WechatHover],
})完整代码
完整的代码见 GitHub 上的 WechatHover.vue 文件。