mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
perf(theme): 优化 headers
This commit is contained in:
parent
5db3481b7e
commit
67f7b0e0c6
@ -9,23 +9,20 @@ import VPDocMeta from '@theme/VPDocMeta.vue'
|
||||
import { useEncrypt } from '../composables/encrypt.js'
|
||||
import { useSidebar } from '../composables/sidebar.js'
|
||||
import { useData } from '../composables/data.js'
|
||||
import { useHeaders } from '../composables/outline.js'
|
||||
|
||||
const { page, theme, frontmatter, isDark } = useData()
|
||||
const route = useRoute()
|
||||
|
||||
const { hasSidebar, hasAside, leftAside } = useSidebar()
|
||||
const headers = useHeaders()
|
||||
const { isPageDecrypted } = useEncrypt()
|
||||
|
||||
const hasComments = computed(() => {
|
||||
return page.value.frontmatter.comments !== false && isPageDecrypted.value
|
||||
})
|
||||
|
||||
const enableAside = computed(() => {
|
||||
if (page.value.isBlogPost)
|
||||
return hasAside.value && isPageDecrypted.value && page.value.headers.length
|
||||
|
||||
return hasAside.value && isPageDecrypted.value
|
||||
})
|
||||
const enableAside = computed(() => hasAside.value && headers.value.length)
|
||||
|
||||
const pageName = computed(() =>
|
||||
route.path.replace(/[./]+/g, '_').replace(/_html$/, ''),
|
||||
@ -68,7 +65,7 @@ watch(
|
||||
<div
|
||||
:key="page.path" class="vp-doc-container" :class="{
|
||||
'has-sidebar': hasSidebar,
|
||||
'has-aside': hasAside,
|
||||
'has-aside': enableAside,
|
||||
'is-blog': page.isBlogPost,
|
||||
'with-encrypt': !isPageDecrypted,
|
||||
}"
|
||||
@ -207,7 +204,7 @@ watch(
|
||||
.aside-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
min-height: calc(100vh - var(--vp-footer-height, 0px));
|
||||
min-height: calc(100vh - var(--vp-nav-height, 0px) - var(--vp-footer-height, 0px));
|
||||
max-height: 100vh;
|
||||
padding-top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 32px);
|
||||
margin-top: calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1 - 32px);
|
||||
@ -241,7 +238,7 @@ watch(
|
||||
.aside-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));
|
||||
min-height: calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-footer-height, 0px) + 48px));
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
|
||||
@ -1,19 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onContentUpdated } from '@vuepress-plume/plugin-content-update/client'
|
||||
import VPDocOutlineItem from '@theme/VPDocOutlineItem.vue'
|
||||
import { type MenuItem, getHeaders, useActiveAnchor } from '../composables/outline.js'
|
||||
import { type MenuItem, useActiveAnchor, useHeaders } from '../composables/outline.js'
|
||||
import { useData } from '../composables/data.js'
|
||||
|
||||
const { theme, frontmatter } = useData()
|
||||
const { theme } = useData()
|
||||
|
||||
const headers = ref<MenuItem[]>([])
|
||||
const headers = useHeaders()
|
||||
const hasOutline = computed(() => headers.value.length > 0)
|
||||
|
||||
onContentUpdated(() => {
|
||||
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
|
||||
})
|
||||
|
||||
const container = ref()
|
||||
const marker = ref()
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { useWindowScroll } from '@vueuse/core'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { onContentUpdated } from '@vuepress-plume/plugin-content-update/client'
|
||||
import VPLocalNavOutlineDropdown from '@theme/VPLocalNavOutlineDropdown.vue'
|
||||
import { useSidebar } from '../composables/sidebar.js'
|
||||
import { type MenuItem, getHeaders } from '../composables/outline.js'
|
||||
import { useHeaders } from '../composables/outline.js'
|
||||
import { useData } from '../composables/data.js'
|
||||
|
||||
const props = defineProps<{
|
||||
@ -14,23 +13,19 @@ const props = defineProps<{
|
||||
|
||||
defineEmits<(e: 'openMenu') => void>()
|
||||
|
||||
const { page, theme, frontmatter } = useData()
|
||||
const { page, theme } = useData()
|
||||
|
||||
const { hasSidebar } = useSidebar()
|
||||
const { y } = useWindowScroll()
|
||||
|
||||
const navHeight = ref(0)
|
||||
|
||||
const headers = ref<MenuItem[]>([])
|
||||
const headers = useHeaders()
|
||||
|
||||
const empty = computed(() => {
|
||||
return headers.value.length === 0 && !hasSidebar.value
|
||||
})
|
||||
|
||||
onContentUpdated(() => {
|
||||
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
navHeight.value = Number.parseInt(
|
||||
getComputedStyle(document.documentElement).getPropertyValue(
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { onMounted, onUnmounted, onUpdated } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { inject, onMounted, onUnmounted, onUpdated, provide, ref } from 'vue'
|
||||
import type { InjectionKey, Ref } from 'vue'
|
||||
import { onContentUpdated } from '@vuepress-plume/plugin-content-update/client'
|
||||
import type { ThemeOutline } from '../../shared/index.js'
|
||||
import { throttleAndDebounce } from '../utils/index.js'
|
||||
import { useAside } from './aside.js'
|
||||
import { useData } from './data.js'
|
||||
|
||||
export interface Header {
|
||||
/**
|
||||
@ -41,6 +43,31 @@ export type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
||||
children?: MenuItem[]
|
||||
}
|
||||
|
||||
export const headersSymbol: InjectionKey<Ref<MenuItem[]>> = Symbol(
|
||||
__VUEPRESS_DEV__ ? 'headers' : '',
|
||||
)
|
||||
|
||||
export function setupHeaders(): Ref<MenuItem[]> {
|
||||
const { frontmatter, theme } = useData()
|
||||
const headers = ref<MenuItem[]>([])
|
||||
|
||||
onContentUpdated(() => {
|
||||
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
|
||||
})
|
||||
|
||||
provide(headersSymbol, headers)
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
export function useHeaders(): Ref<MenuItem[]> {
|
||||
const headers = inject(headersSymbol)
|
||||
if (!headers) {
|
||||
throw new Error('useHeaders() is called without provider.')
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
export function getHeaders(range?: ThemeOutline): MenuItem[] {
|
||||
const headers = Array.from(
|
||||
document.querySelectorAll('.vp-doc :where(h1,h2,h3,h4,h5,h6)'),
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
enhanceScrollBehavior,
|
||||
setupDarkMode,
|
||||
setupEncrypt,
|
||||
setupHeaders,
|
||||
setupSidebar,
|
||||
setupThemeData,
|
||||
setupWatermark,
|
||||
@ -23,6 +24,7 @@ export default defineClientConfig({
|
||||
},
|
||||
setup() {
|
||||
setupSidebar()
|
||||
setupHeaders()
|
||||
setupEncrypt()
|
||||
setupWatermark()
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user