|
1 | 1 | import type { MaybeRef, MaybeRefOrGetter, ReadonlyRefOrGetter } from '@vueuse/shared' |
2 | | -import { toRef, toValue } from '@vueuse/shared' |
| 2 | +import { toRef, toValue, tryOnBeforeUnmount } from '@vueuse/shared' |
3 | 3 | import type { ComputedRef, Ref } from 'vue-demi' |
4 | 4 | import { watch } from 'vue-demi' |
5 | 5 | import { useMutationObserver } from '../useMutationObserver' |
6 | 6 | import type { ConfigurableDocument } from '../_configurable' |
7 | 7 | import { defaultDocument } from '../_configurable' |
8 | 8 |
|
9 | | -export type UseTitleOptionsBase = |
10 | | -{ |
| 9 | +export type UseTitleOptionsBase = { |
11 | 10 | /** |
12 | | - * Observe `document.title` changes using MutationObserve |
13 | | - * Cannot be used together with `titleTemplate` option. |
14 | | - * |
15 | | - * @default false |
| 11 | + * Restore the original title when unmounted |
| 12 | + * @param originTitle original title |
| 13 | + * @returns restored title |
16 | 14 | */ |
17 | | - observe?: boolean |
18 | | -} |
19 | | -| { |
20 | | - /** |
21 | | - * The template string to parse the title (e.g., '%s | My Website') |
22 | | - * Cannot be used together with `observe` option. |
23 | | - * |
24 | | - * @default '%s' |
25 | | - */ |
26 | | - titleTemplate?: MaybeRef<string> | ((title: string) => string) |
27 | | -} |
| 15 | + restoreOnUnmount?: false | ((originalTitle: string, currentTitle: string) => string | null | undefined) |
| 16 | +} & ( |
| 17 | + { |
| 18 | + /** |
| 19 | + * Observe `document.title` changes using MutationObserve |
| 20 | + * Cannot be used together with `titleTemplate` option. |
| 21 | + * |
| 22 | + * @default false |
| 23 | + */ |
| 24 | + observe?: boolean |
| 25 | + } |
| 26 | + | { |
| 27 | + /** |
| 28 | + * The template string to parse the title (e.g., '%s | My Website') |
| 29 | + * Cannot be used together with `observe` option. |
| 30 | + * |
| 31 | + * @default '%s' |
| 32 | + */ |
| 33 | + titleTemplate?: MaybeRef<string> | ((title: string) => string) |
| 34 | + } |
| 35 | +) |
28 | 36 |
|
29 | 37 | export type UseTitleOptions = ConfigurableDocument & UseTitleOptionsBase |
30 | 38 |
|
@@ -56,7 +64,9 @@ export function useTitle( |
56 | 64 | */ |
57 | 65 | const { |
58 | 66 | document = defaultDocument, |
| 67 | + restoreOnUnmount = t => t, |
59 | 68 | } = options |
| 69 | + const originalTitle = document?.title ?? '' |
60 | 70 |
|
61 | 71 | const title: Ref<string | null | undefined> = toRef(newTitle ?? document?.title ?? null) |
62 | 72 | const isReadonly = newTitle && typeof newTitle === 'function' |
@@ -90,6 +100,14 @@ export function useTitle( |
90 | 100 | ) |
91 | 101 | } |
92 | 102 |
|
| 103 | + tryOnBeforeUnmount(() => { |
| 104 | + if (restoreOnUnmount) { |
| 105 | + const restoredTitle = restoreOnUnmount(originalTitle, title.value || '') |
| 106 | + if (restoredTitle != null && document) |
| 107 | + document.title = restoredTitle |
| 108 | + } |
| 109 | + }) |
| 110 | + |
93 | 111 | return title |
94 | 112 | } |
95 | 113 |
|
|
0 commit comments