With it, you can set meta title, description, keywords, and author. Same life cycle as the component which it used in. Reset when the component onUnmounted
. It can be used in the setup
of the composition api, or in created, mounted, and methods
in the traditional Vue component style.
Installation
create HTMLHead.tsx
import {
reactive,
onBeforeUnmount,
Teleport,
getCurrentInstance,
ComponentInternalInstance,
} from 'vue'
const store = reactive({
title: '',
description: '',
keywords: '',
author: '',
})
// try to remove existing elements
try {
for (const sel of [
'title',
'meta[name="description"]',
'meta[name="keywords"]',
'meta[name="author"]',
]) {
const el = document.head.querySelector(sel)
if (el) {
el.remove()
}
}
} catch (error) {}
export function HTMLHead() {
return (
<Teleport to="head">
{store.title && <title>{store.title}</title>}
{store.description && (
<meta name="description" content={store.description} />
)}
{store.keywords && <meta name="keywords" content={store.keywords} />}
{store.author && <meta name="author" content={store.author} />}
</Teleport>
)
}
export const useTitle = generateUseFunction('title')
export const useDescription = generateUseFunction('description')
export const useKeywords = generateUseFunction('keywords')
export const useAuthor = generateUseFunction('author')
function generateUseFunction(name: string) {
return (value: string, vm?: ComponentInternalInstance) => {
// @ts-ignore
store[name] = value
const thevm = vm || getCurrentInstance()
if (!thevm) {
throw new Error(
`HTMLHead use ${name}: the second argument is required when called outside of setup`
)
}
onBeforeUnmount(() => {
// @ts-ignore
if (store[name] === value) {
// @ts-ignore
store[name] = ''
}
}, thevm)
}
}
import HTMLHead
component and append to your root component, such as App.vue
<template>
<div id="app">
<HTMLHead />
</div>
</template>
<script>
import { HTMLHead } from './HTMLHead.tsx'
export default {
components: { HTMLHead },
}
</script>
Usage
import {
useTitle,
useDescription,
useKeywords,
useAuthor,
} from './HTMLHead.tsx'
In setup
setup() {
useTitle('title text')
}
:warning: The second argument is required if used in asynchronous setup or outside of setup.
In created
, mounted
, methods
created() {
useTitle('title text', this)
}
After await in asynchronous setup
async setup() {
const vm = getCurrentInstance()
await something
useTitle('title text', vm)
}
Please tell me if you have more elegant code.
Gitalk 加载中 ...