39209ef591
mirror-to-gitee / mirror (push) Successful in 3s
问题:点「产品功能 / 核心能力 / 界面预览 / 官方文档」跳转后图标不变蓝。 根因:VitePress 的 isActive() 只比较 path,不看 hash。nav 里 「首页 /」「产品功能 /#features」「核心能力 /#core」的路径部分都是 `/`, 默认逻辑要么把首页和当前锚点同时点亮,要么只亮首页。 改动 - 新增 .vitepress/theme/nav-anchor.ts 接管首页内锚点项的激活判定: 用 data-anchor-active 属性标记,规则为 在首页且有 hash → 只有 hash 匹配项亮;在首页无 hash → 只有「首页」亮; 不在首页 → 清标记交回 VitePress 默认逻辑 - 样式侧用 html.portal-nav-home 限定压制默认 active 的作用域, 只影响首页,不影响 /projects/ 与 /about 的正常高亮 - 导航「项目」加 activeMatch: '^/projects/', 使 /projects/iotlcm/ 等详情页也保持高亮 - MutationObserver 监听导航 DOM 变化(SPA 切换、主题切换会重建) 踩的坑 - Layout 是函数式组件,onMounted 在其中无效(Vue 报"no active component instance"),改用 nextTick 调度 - 初版用 hashOf(a) 判空来识别「首页」,但 /projects/ 与 /about 也没有 hash, 被误判成首页项一起点亮;改为判断 href 解析后是否为 '/' - 抑制规则最初没加作用域,导致非首页页面的正常 active 也被压成黑字 验证(8 个场景逐个实测) 首页顶部→首页 / 四个锚点→各自高亮 / 项目页→项目 / 关于页→关于 / iotLCM 详情→项目;构建 13 页 274 引用 0 失效
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import DefaultTheme from 'vitepress/theme'
|
|
import type { Theme } from 'vitepress'
|
|
import { h, watch, nextTick } from 'vue'
|
|
import { useData, useRoute } from 'vitepress'
|
|
|
|
import ProjectList from './components/ProjectList.vue'
|
|
import HomePage from './components/HomePage.vue'
|
|
import CapabilityTabs from './components/CapabilityTabs.vue'
|
|
import FeatureGrid from './components/FeatureGrid.vue'
|
|
import ScreenshotPreview from './components/ScreenshotPreview.vue'
|
|
|
|
import { setupNavAnchorHighlight, applyNavAnchorHighlight } from './nav-anchor'
|
|
|
|
import './styles/portal.css'
|
|
|
|
/**
|
|
* 首页用 layout: page 承载自定义整页排版,
|
|
* 这里给它套一层 .portal-page,把默认窄栏与 padding 去掉。
|
|
* 同时接管导航栏锚点项的高亮(VitePress 默认只认 path,不认 hash)。
|
|
*/
|
|
const PortalLayout = () => {
|
|
const { frontmatter } = useData()
|
|
const route = useRoute()
|
|
|
|
const isPortal = frontmatter.value.layout === 'page'
|
|
|
|
/**
|
|
* Layout 是函数式组件,onMounted 在这里不生效(Vue 会告警),
|
|
* 因此直接在渲染期间调度:等 DOM 落地后跑一次,再靠 MutationObserver 兜住后续变化。
|
|
*/
|
|
if (typeof window !== 'undefined') {
|
|
nextTick(() => setupNavAnchorHighlight())
|
|
}
|
|
|
|
// SPA 路由切换不触发 hashchange,这里补一次
|
|
watch(
|
|
() => [route.path, route.hash],
|
|
() => nextTick(() => applyNavAnchorHighlight())
|
|
)
|
|
|
|
return h('div', { class: isPortal ? 'portal-page' : '' }, h(DefaultTheme.Layout))
|
|
}
|
|
|
|
export default {
|
|
extends: DefaultTheme,
|
|
Layout: PortalLayout,
|
|
enhanceApp({ app }) {
|
|
app.component('ProjectList', ProjectList)
|
|
app.component('HomePage', HomePage)
|
|
app.component('CapabilityTabs', CapabilityTabs)
|
|
app.component('FeatureGrid', FeatureGrid)
|
|
app.component('ScreenshotPreview', ScreenshotPreview)
|
|
},
|
|
} satisfies Theme
|