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')
}
⚠️ 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.