useTitle
Judul halaman, yang bisa dibaca dan ditulis.
Lihat tab peramban Anda — judulnya ikut berubah saat mengetik.
observe menyalakan pengamatan terhadap perubahan dari luar — kode lain, ekstensi, atau router yang menyetelnya sendiri. Mati secara bawaan, sama seperti sumbernya: satu MutationObserver di <head> bukan biaya yang pantas dibayar setiap halaman kalau tidak ada yang benar-benar membutuhkannya.
Judul yang ditulis sendiri diingat, supaya pengamatnya tidak menganggap tulisan sendiri sebagai perubahan dari luar lalu memantulkannya kembali.
Pemasangan
npx shadcn-vue@latest add @kliping/use-title Perlu @kliping terdaftar di components.json project Anda. Lihat cara menyiapkannya.
Ikut terpasang sendiri: is-browser, saat-terpasang.
Salin dulu is-browser, saat-terpasang — masing-masing memuat sumbernya di halamannya sendiri — lalu tempel berkas ini.
import { getCurrentScope, onScopeDispose, ref, toValue, watch } from 'vue'
import type { MaybeRefOrGetter, Ref } from 'vue'
import { isBrowser } from '@/lib/is-browser'
import { saatTerpasang } from '@/lib/saat-terpasang'
export interface UseTitleOptions {
/** Ikuti perubahan judul yang datang dari luar. Bawaan: false. */
observe?: boolean
/** Pola judul akhir. `%s` diganti judulnya, atau berikan fungsi. */
titleTemplate?: string | ((judul: string) => string)
}
function buatPola(pola?: string | ((judul: string) => string)) {
if (typeof pola === 'function')
return pola
if (typeof pola === 'string' && pola.includes('%s'))
return (judul: string) => pola.replaceAll('%s', judul)
return (judul: string) => judul
}
export function useTitle(
newTitle?: MaybeRefOrGetter<string | null | undefined>,
options: UseTitleOptions = {},
) {
const { observe = false, titleTemplate } = options
const format = buatPola(titleTemplate)
const judul = ref(
toValue(newTitle) ?? (isBrowser ? document.title : ''),
) as Ref<string>
// Judul terakhir yang ditulis dari sini. Pengamat memakainya untuk
// membedakan tulisan sendiri dari perubahan yang datang dari luar.
let ditulisSendiri: string | null = null
watch(
() => toValue(newTitle),
(baru) => {
if (baru != null && baru !== judul.value)
judul.value = baru
},
)
watch(
judul,
(baru) => {
if (!isBrowser)
return
const akhir = format(baru)
ditulisSendiri = akhir
if (document.title !== akhir)
document.title = akhir
},
{ immediate: true },
)
let pengamat: MutationObserver | undefined
saatTerpasang(() => {
if (!observe || typeof MutationObserver === 'undefined')
return
const sasaran = document.head ?? document.documentElement
if (!sasaran)
return
pengamat = new MutationObserver(() => {
const kini = document.title
if (ditulisSendiri === kini || judul.value === kini)
return
judul.value = kini
})
pengamat.observe(sasaran, { childList: true, subtree: true, characterData: true })
})
if (getCurrentScope())
onScopeDispose(() => pengamat?.disconnect())
return judul
}API
export interface UseTitleOptions {
/** Ikuti perubahan judul yang datang dari luar. Bawaan: false. */
observe?: boolean
/** Pola judul akhir. `%s` diganti judulnya, atau berikan fungsi. */
titleTemplate?: string | ((judul: string) => string)
}
export function useTitle(
newTitle?: MaybeRefOrGetter<string | null | undefined>,
options: UseTitleOptions = {},
)