Vue组件里动态设置SEO标题和meta标签为什么没效果?
我在用Vue 3开发博客页面时,想在组件里动态设置SEO标题和description标签。按照文档用了vue-meta插件,但页面加载后这些标签都没渲染出来,浏览器标题还是默认的”Vue App”。
代码是这样的:
<template>
<div>
<Head>
<Title>{{ article.title }} | 博客</Title>
<Meta name="description" :content="article.summary" />
</Head>
<!-- 页面内容 -->
</div>
</template>
<script setup>
import { ref } from 'vue'
const article = ref({ title: '测试文章', summary: '这是测试简介' })
</script>
我已经安装了vue-meta并在main.js里注册了,但控制台没报错。用开发者工具查看head标签时,连meta标签的结构都没生成。是不是动态数据加载顺序有问题?或者需要额外配置什么?
vue-meta这个老版本插件,但它在 Vue 3 里其实已经不维护了,而且和 Vue 3 的 Composition API 不太兼容,所以你写<Head><Title>这些标签根本不会被识别,也不会被渲染到<head>里。Vue 3 推荐用的是
@vueuse/head这个库,它更轻量、更符合 Vue 3 的风格,也支持 SSR(服务端渲染),而且和 Composition API 天然契合。下面我给你一步步来改:
第一步,先卸载旧的
vue-meta(如果装了的话):第二步,装新库:
第三步,在
main.js里正确注册(注意不是app.use(),而是直接挂载到 app 的config.globalProperties里,或者更推荐的方式是用app.use()但得用新写法):这里要注意:一定要在
createApp之后、mount之前调用createHead()并app.use(head),顺序错了也会不生效。第四步,改你的组件写法:
这里要注意几个细节:
-
title和content都可以写成函数,这样当article是响应式数据时,它会自动更新 head 内容,不需要你手动 watch- 如果你用的是静态值,也可以直接写字符串,比如
title: '固定标题'- 有些浏览器里你可能看到 title 没变,但刷新一下页面(或者在开发者工具的 Network 里切到 Disable cache)就能看到效果
第五步,验证是否生效:
打开浏览器开发者工具,切换到 Elements 标签,找到
<head>,你应该能看到类似这样的内容:如果还是没变化,建议你检查:
- 确保
main.js里app.use(head)写对了位置(必须在app.mount之前)- 确保你没在
head里手动写死<title>Vue App</title>,如果写死了,后面动态设置的可能会被覆盖(虽然一般不会,但有时候会)- 如果你用了 Vue Router,确保路由跳转时组件确实被重新渲染了(不是 keep-alive 缓存的)
另外,如果你项目里用了 SSR(比如 Nuxt),那这套写法也适用,但得注意
useHead要在组件 setup 里调用,不能放在onMounted里,不过你这应该是 SPA,所以没问题。我之前踩过一个坑:用
vue-meta的时候,文档写得挺模糊,它要求你在组件里写<Head>,但这个组件必须是根组件或者某个特定结构,而 Vue 3 里根本没这个限制——@vueuse/head直接用useHead函数,更灵活也更符合 Vue 3 的习惯。如果按上面步骤还是不行,把你的
main.js和组件完整代码贴出来,我帮你看看是不是哪里漏了。把代码改成这样:
记得先安装依赖
npm install @vueuse/head,然后在main.js里注册import { createHead } from '@vueuse/head'; app.use(createHead())。动态数据建议在onMounted里设置,确保加载顺序没问题。