小试牛刀
在nuxt中,定义路由非常简单
在app目录下创建一个pages目录,然后里面的vue文件就是路径
nuxt4之前的版本,pages目录是在项目根目录下的,新版本之后是需要放在app目录下
判断是不是新版本,就看脚手架创建的这个项目,有没有app目录就知道了
举个例子
app
pages
about.vue
article
index.vue
app.vue
对应about.vue的访问路径就是 /about
对应article/index.vue的访问路径就是 /article
需要把app.vue改一下
<script setup lang="ts">
</script>
<template>
<div>
<nuxt-page></nuxt-page>
</div>
</template>
重点就是使用 nuxt-page组件
这个组件会自动发现pages下面的vue组件
SSR vs CSR 渲染流程
- 服务端渲染 (SSR): 所有的内容(标题、段落、数据)在离开服务器之前就已经填入到 HTML 页面中。浏览器拿到的是一个已经可以阅读的完整文档,右键“查看网页源代码”能看到完整内容。
- 客户端渲染 (CSR): 页面本身是一个空的“骨架”,内容需要依靠 JavaScript 在用户浏览器(客户端)内执行并请求数据后才能显示。右键“查看网页源代码”只能看到一个空的占位符。

| 特性 | SSR (Nuxt 默认) | CSR (传统 SPA) |
|---|---|---|
| SEO 搜索引擎优化 | 极好。爬虫直接读取完整 HTML。 | 较差。爬虫看到的是空壳。 |
| 首屏加载速度 (FCP) | 快。内容随 HTML 一起到达。 | 慢。需等 JS 下载并执行完。 |
| 服务器压力 | 大。服务器要负责实时生成页面。 | 小。服务器只负责传文件。 |
| 用户体验 | 页面跳转有时会有短暂白屏。 | 初次加载慢,但后续页面切换极快。 |
动态路由
像文章详情,用户详情这些页面,并不是一个页面,而是动态的页面
访问路径大概是这样的
/article/1
/article/2
这就需要我们在定义的时候,做一些特殊处理
app
pages
about.vue
article
[id].vue
app.vue
然后在[id].vue里面
<script setup lang="ts">
import {useRoute} from "vue-router";
const route = useRoute()
const articleId = route.params.id
</script>
<template>
<div>
文章详情页面: 文章id {{ articleId }}
</div>
</template>
definePageMeta
对于动态路由[id].vue,如果用户访问/article/abc(id 应该是数字),页面可能会崩溃或显示异常。
definePageMeta({
validate: async (route) => {
// 检查 id 是否为数字
return /^\d+$/.test(route.params.id as string) // 匹配失败会跳转到404页面
}
})
多个路由参数?
/article/1/comment/1
pages
article
[articleID]
comment
[commentID].vue
[id].vue
index.vue
特殊的页面 表示 /
pages/index.vue 表示 /
pages/user/index.vue 表示 /user
那pages/user.vue 表示?
嵌套路由
如果存在pages/parent.vue和pages/parent/child.vue,那么parent.vue内部也需要一个<NuxtPage />来承载子页面内容。
useHead用法
专门用来管理页面元数据(Metadata)。
简单来说,它的作用就是让你在 Vue 组件中,动态地修改 HTML 文档里的<head> 部分。比如修改网页标题、添加 CSS 链接、插入脚本
修改title
希望访问不同的页面,网站的title有不同的变化,需要使用nuxt给我们提供的useHead 函数
<script setup lang="ts">
// 直接写就行,这些声明已经在.nuxt里面了
useHead({
title: '关于我们 - 枫枫知道的网站',
meta: [
{ name: 'description', content: '这是关于页面的描述,对 SEO 非常友好' }
]
})
</script>
<template>
<div>
<h1>关于页面</h1>
<p>hello, 这是一个 SSR 渲染的页面</p>
</div>
</template>
<style scoped>
/* 你的样式 */
</style>
优先级:如果页面有useHead的配置,就用自己的,没有就找父级,直到app.vue
如果你的编辑器看到useHead 这些爆红的话,改一下tsconfig.json,或者升级webstoram版本
{
"extends": "./.nuxt/tsconfig.json", // 强制让编辑器读取主配置
"files": [],
"references": [
{ "path": "./.nuxt/tsconfig.app.json" },
{ "path": "./.nuxt/tsconfig.server.json" },
{ "path": "./.nuxt/tsconfig.shared.json" },
{ "path": "./.nuxt/tsconfig.node.json" }
]
}
- 管理复杂的body和html属性
有时候你需要在特定的页面给<body>标签加个类名(比如暗黑模式或特定背景),或者修改<html>的语言属性,useHead也能轻松搞定:
useHead({
htmlAttrs: {
lang: 'zh-CN'
},
bodyAttrs: {
class: 'article-theme-dark'
}
})
- 插入外部资源
如果你某个页面需要引入一个第三方的 JS 库(比如地图 SDK、统计代码),没必要全局引入,直接局部挂载:
useHead({
script: [
{
src: 'https://example.com/map-sdk.js',
defer: true, // 延迟加载
tagPosition: 'bodyClose' // 放到 body 结束标签前,避免阻塞渲染
}
],
link: [
{ rel: 'icon', type: 'image/png', href: '/favicon.png' }
]
})
全局标题模板
你肯定不想在每个页面都写 - 枫枫知道。可以在nuxt.config.ts中配置一个全局模板
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
titleTemplate: '%s - 枫枫知道', // %s 会被页面里定义的 title 替换
charset: 'utf-8',
viewport: 'width=device-width, initial-scale=1',
}
}
})
优先级:如果
app.vue定义了标题,而pages/index.vue也定义了,那么组件树中越深层的配置会覆盖上层的配置。
seo优化
Nuxt 推荐在大多数 SEO 场景下使用useSeoMeta。它是useHead的“快捷方式”,专门为meta标签设计,有非常棒的TypeScript 自动补全,能防止你写错og:title或twitter:card等属性。
useSeoMeta({
title: '我的文章标题',
ogTitle: '我的文章标题',
description: '这是文章的详细描述',
ogDescription: '这是在社交媒体上显示的详细描述',
ogImage: 'https://example.com/cover.jpg',
twitterCard: 'summary_large_image',
})
基础 SEO 属性 (Standard Meta Tags)
这些属性是给搜索引擎(Google, 百度)看的,决定了搜索结果的排名和展示样式。
title: 页面标题。这是 SEO 最核心的指标,会显示在搜索结果的第一行蓝色文字上。description: 页面描述。通常是搜索结果标题下方的摘要文字。字数建议控制在 150 个字符左右。keywords: 关键词。虽然现在主流搜索引擎(如 Google)已经不再将其作为排名依据,但国内某些搜索引擎依然会参考。author: 作者名。标明文章的原创者。
Open Graph 属性 (OG 协议)
这些属性以og开头,由 Facebook 推出,现在已成为行业标准。当有人在微信、Discord、Telegram 等社交软件分享你的链接时,显示的“卡片预览”就是靠它们。
ogTitle: 分享卡片上的标题(通常和title一致)。ogDescription: 分享卡片上的描述。ogImage:极其重要!这是分享卡片上的预览图。如果没有它,分享链接只会显示一段枯燥的文字。ogUrl: 页面的规范链接。ogType: 页面类型,常用的是website或article。

文章详情的示例
useSeoMeta({
// 基础信息
title: 'Nuxt 3 实战教程:从零重构博客 - 枫枫知道',
description: '这是一门关于如何使用 Nuxt 3 解决前后端分离 SEO 痛点的课程...',
keywords: 'Nuxt3, Vue3, SSR, SEO优化, 枫枫知道',
// 社交分享 (微信、QQ、Discord等)
ogTitle: 'Nuxt 3 实战教程:从零重构博客',
ogDescription: '这是一门关于如何使用 Nuxt 3 解决前后端分离 SEO 痛点的课程...',
ogImage: 'https://api.fengfeng.com/covers/nuxt-tutorial.png', // 必须是绝对路径
ogType: 'article',
// Twitter 优化
twitterCard: 'summary_large_image',
twitterSite: '@fengfeng_zhidao',
})