可以设置 meta title, description, keywords, author. 与组件同生命周期, 组件卸载时还原. 可以在 composition api 的 setup 里使用, 也可以再 Vue 传统组件写法里的 created, mounted, methods 里使用.
安装
创建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);
};
}
引入 HTMLHead 组件并附加到根组件中, 如App.vue
<template>
<div id="app">
<HTMLHead />
</div>
</template>
<script>
import { HTMLHead } from "./HTMLHead.tsx";
export default {
components: {},
};
</script>
使用
import {
useTitle,
useDescription,
useKeywords,
useAuthor,
} from "./HTMLHead.tsx";
在 setup 中使用
setup() {
useTitle('title text')
}
⚠️ 在异步 setup 及 setup 以外使用需要第二个参数.
在created
, mounted
, methods
中使用
created() {
useTitle('title text', this)
}
在 异步 setup 的 await 之后使用
async setup() {
const vm = getCurrentInstance()
await something
useTitle('title text', vm)
}
如果你有更好的写法, 请告诉我.