diff --git a/docs/en/reference/default-theme-config.md b/docs/en/reference/default-theme-config.md index 8f71d4af..39c3fcf7 100644 --- a/docs/en/reference/default-theme-config.md +++ b/docs/en/reference/default-theme-config.md @@ -466,7 +466,7 @@ Returns layout-related data. The returned object has the following type: interface { isHome: ComputedRef - sidebar: ComputedRef + sidebar: Readonly> sidebarGroups: ComputedRef hasSidebar: ComputedRef isSidebarEnabled: ComputedRef @@ -474,7 +474,7 @@ interface { hasAside: ComputedRef leftAside: ComputedRef - headers: ShallowRef + headers: Readonly> hasLocalNav: ComputedRef } ``` diff --git a/src/client/theme-default/composables/layout.ts b/src/client/theme-default/composables/layout.ts index 85fb306b..1b993ea6 100644 --- a/src/client/theme-default/composables/layout.ts +++ b/src/client/theme-default/composables/layout.ts @@ -1,28 +1,23 @@ -import { useMediaQuery } from '@vueuse/core' -import { onContentUpdated, useRoute } from 'vitepress' -import type { DefaultTheme } from 'vitepress/theme' -import { computed, shallowRef, watch } from 'vue' +import { inBrowser, onContentUpdated, useRoute } from 'vitepress' +import type { DefaultTheme, useLayout as expected } from 'vitepress/theme' +import { computed, shallowReadonly, shallowRef, watch } from 'vue' import { getSidebar, getSidebarGroups } from '../support/sidebar' import { useData } from './data' import { getHeaders } from './outline' import { useCloseSidebarOnEscape } from './sidebar' const headers = shallowRef([]) +const sidebar = shallowRef([]) -export function useLayout() { - const { frontmatter, page, theme } = useData() - const is960 = useMediaQuery('(min-width: 960px)') +const is960 = shallowRef(false) + +export function useLayout(): ReturnType { + const { frontmatter, theme } = useData() const isHome = computed(() => { return !!(frontmatter.value.isHome ?? frontmatter.value.layout === 'home') }) - const sidebar = computed(() => { - const sidebarConfig = theme.value.sidebar - const relativePath = page.value.relativePath - return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [] - }) - const hasSidebar = computed(() => { return ( frontmatter.value.sidebar !== false && @@ -56,13 +51,13 @@ export function useLayout() { return { isHome, - sidebar, + sidebar: shallowReadonly(sidebar), sidebarGroups, hasSidebar, isSidebarEnabled, hasAside, leftAside, - headers, + headers: shallowReadonly(headers), hasLocalNav } } @@ -72,12 +67,36 @@ interface RegisterWatchersOptions { } export function registerWatchers({ closeSidebar }: RegisterWatchersOptions) { - const { frontmatter, theme } = useData() + const { frontmatter, page, theme } = useData() + + watch( + () => [page.value.relativePath, theme.value.sidebar] as const, + ([relativePath, sidebarConfig]) => { + const newSidebar = sidebarConfig + ? getSidebar(sidebarConfig, relativePath) + : [] + if (JSON.stringify(newSidebar) !== JSON.stringify(sidebar.value)) { + sidebar.value = newSidebar + } + }, + { immediate: true, deep: true, flush: 'sync' } + ) onContentUpdated(() => { headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline) }) + if (inBrowser) { + is960.value = window.innerWidth >= 960 + window.addEventListener( + 'resize', + () => { + is960.value = window.innerWidth >= 960 + }, + { passive: true } + ) + } + const route = useRoute() watch(() => route.path, closeSidebar) diff --git a/theme.d.ts b/theme.d.ts index 0e037da7..9d666400 100644 --- a/theme.d.ts +++ b/theme.d.ts @@ -16,7 +16,7 @@ export default theme export declare const useLayout: () => { isHome: ComputedRef - sidebar: ComputedRef + sidebar: Readonly> sidebarGroups: ComputedRef hasSidebar: ComputedRef isSidebarEnabled: ComputedRef @@ -27,7 +27,7 @@ export declare const useLayout: () => { /** * The outline headers of the current page. */ - headers: ShallowRef + headers: Readonly> /** * Whether the current page has a local nav. Local nav is shown when the * "outline" is present in the page. However, note that the actual