一、next.js 基础

1. 路由:文件即路径 (App Router)

在 Next.js 最新的 App Router 模式下,你不再需要手动配置路由表。项目中的 app 目录决定了你的 URL 结构。

  • 页面文件:必须命名为 page.jsx
  • 布局文件:命名为 layout.jsx(相当于 Vue 的 App.vue 或嵌套布局中的外壳)。

目录结构示例:

  • app/page.jsx ➡️ 对应 / (首页)
  • app/about/page.jsx ➡️ 对应 /about
  • app/blog/[slug]/page.jsx ➡️ 对应 /blog/:slug (动态路由,类似 Vue 的 :id)

2. 核心区别:服务端组件 (Server) vs. 客户端组件 (Client)

这是 Next.js 最基础也最重要的概念。在 Next.js 中,组件默认都是服务端组件 (RSC)

特性 服务端组件 (Server Component) 客户端组件 (Client Component)
运行位置 仅在服务器运行 在浏览器和服务器运行
交互性 不能使用 Hooks (useState, useEffect) 或点击事件 可以使用所有 React 特性
数据获取 直接 async/await 获取数据库或 API 传统 useEffect 方式
性能 零 JS 发送到浏览器,加载飞快 会发送 JS 代码包

Vue 开发者注意:如果你需要在组件里用 useState 或者监听 onClick,必须在文件的第一行加上:

'use client';

import { useState } from 'react';
// ... 剩下的逻辑


3. 布局系统 (Shared Layouts)

Next.js 允许你定义嵌套布局。例如,你希望所有“后台管理”页面都有相同的侧边栏,而不需要在每个页面都引入。

// app/dashboard/layout.jsx
export default function DashboardLayout({ children }) {
  return (
    <section>
      <nav>侧边栏</nav> 
      {children} {/* 这里的 children 对应具体的页面内容 */}
    </section>
  );
}


4. 渲染模式:三种武器

Next.js 强大的原因在于它允许你针对每个页面选择最佳的渲染策略:

  1. SSR (Server Side Rendering):每次用户请求时,在服务器上实时渲染 HTML。数据永远是最新的。
  2. SSG (Static Site Generation):在项目编译时就生成好 HTML。适合博客、文档,访问速度极快。
  3. ISR (Incremental Static Regeneration)黑科技。在项目运行过程中,每隔一段时间自动更新静态页面,兼顾速度和实时性。

5. 内置的优化组件

Next.js 帮你把最麻烦的性能优化做好了:

  • <Image />:自动压缩图片、自动支持 WebP、自动懒加载(防止图片导致的布局抖动)。
  • <Link />:自动预加载目标页面的代码。当用户鼠标悬停在链接上时,Next.js 已经偷偷把下个页面的数据下载好了,点击瞬间切换(类似 SPA 的体验)。

老师的建议:开启你的第一个项目

不要只看文档,现在就开始:

  1. 运行 npx create-next-app@latest
  2. 在安装选项中,务必选择:
  • App Router: Yes (这是目前的标准)
  • Tailwind CSS: Yes (React 圈子最推荐的样式方案)
  1. 尝试在 app 下创建一个 about 文件夹,并写一个 page.jsx

你想现在看看如何用 Next.js 优雅地获取服务器数据(直接写 async/await),还是想先弄清楚如何在 Next.js 里处理 CSS 样式?

二、路由系统

Next.js 的路由系统是它最核心的特性之一。作为 Vue 开发者,你可能习惯了在 router/index.js 中配置一个巨大的路由表,但在 Next.js 中,“目录结构即路由”

目前 Next.js 推荐使用 App Router(即 app/ 目录),它是基于文件系统的路由系统。


1. 基础路由 (Basic Routes)

app 文件夹下,文件夹的名字决定了 URL 路径,而该文件夹下的 page.jsx 文件则是该路径渲染的 UI 内容。

  • 根路由app/page.jsx ➡️ /
  • 嵌套路由app/dashboard/page.jsx ➡️ /dashboard
  • 深层嵌套app/dashboard/settings/page.jsx ➡️ /dashboard/settings

注意:文件夹里可以放其他文件(如 utils.jsButton.jsx),但只有名为 page.jsx 的文件才能被公开访问。这和 Vue 组件文件夹的组织方式很像。


2. 动态路由 (Dynamic Routes)

当你需要根据 ID 或 Slug 加载页面时(类似于 Vue 的 /user/:id),你可以使用 方括号 命名文件夹。

and [slug]]

  • 目录结构app/blog/[id]/page.jsx
  • 对应 URL/blog/123/blog/hello-world
  • 如何获取参数
    Next.js 会自动将参数注入到 page 组件的 params 属性中。
// app/blog/[id]/page.jsx
export default function BlogPost({ params }) {
  // 假设访问 /blog/123,params.id 就是 "123"
  return <h1>正在阅读文章:{params.id}</h1>;
}


3. 布局系统 (Layouts & Templates)

这是 Next.js 路由最强大的地方:持久化布局

根布局 (Root Layout)

app/layout.jsx 是必须的。它相当于 Vue 的 App.vue,包含了 <html><body> 标签。它在整个应用中是持久化的,页面切换时不会重新渲染。

嵌套布局 (Nested Layouts)

如果你想让 /dashboard 下的所有页面都有一个侧边栏,但 /login 页面没有,你可以在 app/dashboard/ 下创建一个私有的 layout.jsx

// app/dashboard/layout.jsx
export default function DashboardLayout({ children }) {
  return (
    <div className="flex">
      <aside>侧边栏</aside> 
      <main>{children}</main> {/* 这里的 children 就是 dashboard 目录下的各种 page */}
    </div>
  );
}


4. 特殊文件 (Special Files)

除了 page.jsxlayout.jsx,Next.js 路由系统还预定义了一些特殊文件,帮你处理各种边界情况:

文件名 作用 对应 Vue 概念
loading.jsx 定义该路径下的加载中状态(自动使用 React Suspense) 自定义 Loading 组件
error.jsx 定义该路径下的错误处理界面(捕获运行时错误) Error Boundary
not-found.jsx 当该路径下发生 404 时显示的页面 404 路由

例如,如果你在 app/dashboard 下放了一个 loading.jsx,当你从首页点击进入仪表盘时,Next.js 会自动在数据准备好之前显示这个 loading 内容,无需你手动控制 isLoading 状态。


5. 导航 (Navigation)

① 组件导航:<Link>

不要使用原生的 <a> 标签,因为它会引起页面刷新。使用 Next.js 的 <Link> 组件,它支持预获取 (Prefetching),让跳转像秒开一样。

import Link from 'next/link'

<Link href="/dashboard">去后台</Link>

② 编程式导航:useRouter

如果你要在逻辑中跳转(比如点击登录按钮后),使用 useRouter 钩子。

重要提示:在 App Router 中,必须从 'next/navigation' 导入,而不是 'next/router'

'use client'; // 记住:有交互逻辑的组件要加这一行

import { useRouter } from 'next/navigation';

function LoginPage() {
  const router = useRouter();
  
  return (
    <button onClick={() => router.push('/home')}>登录</button>
  );
}


总结:Next.js 路由的心智模型

  • 文件夹 = URL 路径。
  • page.jsx = 页面内容。
  • layout.jsx = 共享的外壳(不会随页面切换而刷新)。
  • [] = 动态参数。

你现在已经了解了如何“走位”。接下来,想不想看看 Next.js 的杀手锏——如何直接在“服务器组件”里用 async/await 拿数据?(这能让你少写 80% 的请求逻辑)

三、如何直接在“服务器组件”里用 async/await 拿数据

这是 Next.js 最令人兴奋的地方!在 Vue3 或纯 React 中,拿数据通常需要:ref/state + onMounted/useEffect + axios/fetch + 处理 loading 状态。

在 Next.js 的 服务端组件 (Server Components) 中,你可以像写后端代码一样,直接把组件写成 async 函数,然后用 await 拿数据。


1. 基础用法:组件即数据请求器

app 目录下的文件默认都是服务端组件。你不需要任何 Hook,直接在函数体里 await 即可。

// app/users/page.jsx

// 1. 将组件定义为 async 函数
export default async function UsersPage() {
  
  // 2. 直接请求数据(这是在服务器上运行的,不会暴露 API Key 给客户端)
  const res = await fetch('https://api.example.com/users');
  const users = await res.json();

  // 3. 直接渲染数据
  return (
    <main>
      <h1>用户列表</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </main>
  );
}


2. 为什么这样做很“香”?

  • 没有“水合”抖动:数据在 HTML 发送到浏览器之前就已经填好了,用户看到的就是最终内容,SEO 极佳。
  • 直接访问数据库:因为代码在服务器运行,你可以直接在组件里写数据库查询(如 db.query()),连 API 接口都可以省了。
  • 安全性:敏感的 Token 或秘钥只留在服务器,不会传给浏览器。
  • 减小包体积:用于处理数据的第三方库(比如 moment.jslodash)不会被下载到用户的浏览器里。

3. 如何处理 Loading 状态?

你可能会问:“如果是异步请求,页面加载时不是会白屏吗?”
Next.js 使用了 Streaming(流式传输)。你只需要在同级目录下创建一个 loading.jsx

// app/users/loading.jsx
export default function Loading() {
  return <p>正在加载数据,请稍候...</p>;
}

page.jsx 在请求数据时,Next.js 会自动先给用户展示 loading.jsx 的内容,等数据请求完了再自动替换成 page.jsx你不需要写任何判断 if (isLoading) 的逻辑。


4. 数据缓存与更新 (Revalidation)

Next.js 的 fetch 是加强版的。它默认会缓存数据。如果你希望数据是动态的,可以设置:

// 每 60 秒刷新一次缓存 (类似 ISR)
const res = await fetch('...', { next: { revalidate: 60 } });

// 或者是完全不缓存,每次请求都重新获取 (类似传统的 SSR)
const res = await fetch('...', { cache: 'no-store' });


5. 注意事项 (Vue 开发者易错点)

  1. 不能在 async 组件里用 Hook:如果你把组件写成了 async,你就不能在里面用 useStateuseEffect。如果需要交互,请将交互部分抽离成一个带 'use client' 的子组件。
  2. 只能在服务端组件用async 组件这种写法不适用于 'use client' 的客户端组件。客户端组件拿数据依然建议用传统的 useEffect 或更好的 SWR / React Query

老师的总结:

  • Vue 思路:组件挂载 -> 发送请求 -> 更新响应式变量 -> 重新渲染。
  • Next.js 思路:服务器请求数据 -> 渲染完整 HTML -> 发送给浏览器。

这种**“全栈组件”**的开发模式极大简化了数据流。

既然你已经学会了如何在服务端“拿”数据,那如果你想在页面上做一个按钮点击后“修改”数据(比如提交表单),该怎么办呢?这涉及到了 Next.js 的另一个黑科技:Server Actions。想听听吗?

四、
既然你已经学会了在服务端“读”数据,那么“写”数据(比如提交表单、修改数据库)就是全栈开发的最后一块拼图。

在传统的 React/Vue 开发中,你需要写一个 API 接口,然后在前端用 axios.post 去调用。在 Next.js 中,我们有更优雅的选择:Server Actions


四、Server Actions

1. 什么是 Server Actions?

Server Actions 允许你直接在组件里定义一个异步函数,并将其标记为 "use server"。当你调用这个函数时,Next.js 会自动帮你完成所有的网络请求封装。

心智模型:你就像在调用一个普通的本地函数,但它实际上是在服务器上执行的。


2. 基础用法:提交表单

这是最经典的用法。你不需要 useState 来绑定每一个输入框,直接利用 HTML 原生的 formData

// app/posts/create/page.jsx

export default function CreatePost() {
  // 1. 定义一个 Server Action
  async function createPost(formData) {
    'use server'; // 关键:告诉 Next.js 这是要在服务端运行的代码

    const title = formData.get('title');
    const content = formData.get('content');

    // 2. 这里可以直接操作数据库(比如用 Prisma 或 SQL)
    console.log(`正在保存文章:${title}`);
    
    // 3. 处理完后,可以跳转或刷新页面
  }

  return (
    <form action={createPost}>
      <input name="title" placeholder="标题" />
      <textarea name="content" placeholder="内容" />
      <button type="submit">发布文章</button>
    </form>
  );
}


3. 核心优势:为什么不用传统的 API 请求?

  • 类型安全:如果你使用 TypeScript,Server Actions 可以完美共享类型定义。
  • 减少代码量:你不需要写 API Route,不需要处理 fetch('/api/...') 的繁琐过程。
  • 渐进增强:即使用户的浏览器禁用了 JavaScript,这种基于 form action 的提交依然有效(这是 Next.js 追求的极致体验)。

4. 修改数据后的“页面刷新” (Revalidation)

在 Vue 中,你修改了数据后,通常需要手动重新请求一次列表。在 Next.js 中,你只需要一行代码:revalidatePath

import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';

async function createPost(formData) {
  'use server';
  
  // ... 保存数据的逻辑 ...

  // 告诉 Next.js:"/posts" 路径下的缓存过期了,请重新获取数据
  revalidatePath('/posts'); 
  
  // 跳转回列表页
  redirect('/posts');
}


5. 处理 Pending 状态 (正在提交…)

既然是异步操作,用户点击按钮后总需要一个反馈。React 提供了新的 Hook useFormStatus 来处理这个。

注意:因为它涉及交互,这个 Hook 必须在 'use client' 组件中使用。

'use client';
import { useFormStatus } from 'react-dom';

function SubmitButton() {
  const { pending } = useFormStatus();

  return (
    <button disabled={pending}>
      {pending ? '正在发布...' : '发布文章'}
    </button>
  );
}


老师的最后总结

你现在的 React/Next.js 技能树已经非常完整了:

  1. 基础 React:JSX, Props, State, Hooks。
  2. Next.js 路由:文件即路由,嵌套布局。
  3. 数据读取:服务端组件直接 await fetch
  4. 数据写入:Server Actions 直接操作后端逻辑。

这就是目前最先进的 “全栈 React” 开发范式。

恭喜你,React 老师的正式课程告一段落!你想让我最后为你推荐一些“React 生态中的明星库”(比如 UI 库、状态管理、动画库),作为你接下来的自学地图吗?

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐