nuxt路由即页面
小试牛刀 在nuxt中,定义路由非常简单 在app目录下创建一个pages目录,然后里面的vue文件就是路径 nuxt4之前的版本,pages目录是在项目根目录下的,新版本之后是需要放在app

nuxt路由即页面

发布时间:2026-04-21 (2026-04-21)
AI 文章总结
用 AI 快速提炼本文核心内容和阅读重点。

小试牛刀

在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.vuepages/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" }
  ]
}
  1. 管理复杂的body和html属性

有时候你需要在特定的页面给<body>标签加个类名(比如暗黑模式或特定背景),或者修改<html>的语言属性,useHead也能轻松搞定:

useHead({
  htmlAttrs: {
    lang: 'zh-CN'
  },
  bodyAttrs: {
    class: 'article-theme-dark'
  }
})
  1. 插入外部资源

如果你某个页面需要引入一个第三方的 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:titletwitter: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: 页面类型,常用的是websitearticle

文章详情的示例

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',
})