Logo
Published on

Next.js 入门到进阶:(六) API 路由

Authors
  • avatar
    Name
    xiaobai
    Twitter

借助 API 路由,Next.js 成为了一个真正的全栈框架。你可以在同一个项目中同时管理前端页面和后端接口,极大地简化了开发和部署。

在 App Router 中,API 路由被称为 Route Handlers

1. 创建你的第一个 API 路由

Route Handlers 定义在一个名为 route.ts (或 .js) 的文件中。这个文件所在的目录路径决定了 API 的访问地址。

让我们来创建一个简单的 "Hello World" API,地址为 /api/hello

  1. src/app 目录下,创建 api 目录。
  2. api 目录下,创建 hello 目录。
  3. src/app/api/hello 目录下,创建一个 route.ts 文件。

文件结构:

src/
└── app/
    └── api/
        └── hello/
            └── route.ts // /api/hello 接口

现在,向 route.ts 文件中添加以下代码:

// src/app/api/hello/route.ts

import { NextResponse } from 'next/server';

// 导出一个名为 GET 的函数来处理 GET 请求
export async function GET(request: Request) {
  return NextResponse.json({ message: 'Hello, World!' });
}

保存文件后,在浏览器中访问 http://localhost:3000/api/hello,你将看到返回的 JSON 数据:

{
  "message": "Hello, World!"
}

2. 处理不同的 HTTP 方法

一个 route.ts 文件可以导出一系列以 HTTP 方法命名(大写)的函数,来处理不同的请求类型。

支持的 HTTP 方法包括:GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

处理 POST 请求

让我们来扩展上面的例子,让它也能处理 POST 请求。

修改 src/app/api/hello/route.ts

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({ message: 'This was a GET request!' });
}

export async function POST(request: Request) {
  // 从请求体中解析 JSON 数据
  const data = await request.json();

  return NextResponse.json({ 
    message: 'This was a POST request!',
    yourData: data 
  });
}

现在,你可以使用 Postman 或 curl 等工具来测试 POST 请求:

curl -X POST http://localhost:3000/api/hello \
-H "Content-Type: application/json" \
-d '{"name": "Alice"}'

你将会收到以下响应:

{
  "message": "This was a POST request!",
  "yourData": {
    "name": "Alice"
  }
}

3. 动态 API 路由

和页面路由一样,API 路由也可以是动态的。这对于创建 RESTful API 非常有用,例如 /api/users/[userId]

我们来创建一个获取特定文章的 API,地址为 /api/posts/[id]

  1. src/app/api 下创建 posts 目录。
  2. posts 目录下创建 [id] 目录。
  3. [id] 目录下创建 route.ts 文件。

文件结构:

src/app/api/
└── posts/
    └── [id]/
        └── route.ts // /api/posts/:id 接口

编辑 route.ts 文件:

// src/app/api/posts/[id]/route.ts

import { NextResponse } from 'next/server';

type RouteParams = {
  params: {
    id: string;
  }
}

export async function GET(request: Request, { params }: RouteParams) {
  const postId = params.id; // 从 params 对象中获取动态 ID

  // 在实际应用中,你会在这里根据 postId 从数据库查询数据
  // 这里我们用假数据代替
  const post = {
    id: postId,
    title: `文章 ${postId}`,
    content: `这是文章 ${postId} 的内容。`,
  };

  return NextResponse.json(post);
}

现在访问 http://localhost:3000/api/posts/123,你将得到:

{
  "id": "123",
  "title": "文章 123",
  "content": "这是文章 123 的内容。"
}

4. 在客户端组件中调用 API

现在我们有了一个 API,就可以在客户端组件中使用 fetch 来调用它了。

下面是一个简单的表单,它使用 POST 请求将数据提交到我们之前创建的 /api/hello 接口。

'use client';

import { useState } from 'react';

export default function ApiTestForm() {
  const [name, setName] = useState('');
  const [response, setResponse] = useState(null);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    const res = await fetch('/api/hello', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ name }),
    });

    const data = await res.json();
    setResponse(data);
  };

  return (
    <div className="p-8">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="输入你的名字"
          className="border p-2 rounded"
        />
        <button type="submit" className="ml-2 bg-blue-500 text-white p-2 rounded">
          提交
        </button>
      </form>

      {response && (
        <pre className="mt-4 p-4 bg-gray-100 rounded">
          {JSON.stringify(response, null, 2)}
        </pre>
      )}
    </div>
  );
}

总结

Route Handlers 是在 Next.js 中构建后端 API 的强大工具。

  • 通过在 app 目录下创建 route.ts 文件来定义 API 路由。
  • 导出的 GET, POST 等函数分别处理对应的 HTTP 请求。
  • 支持与页面路由相同的动态路由机制。
  • 让你的 Next.js 应用成为一个功能完整的全栈应用

在下一篇教程中,我们将对比 App Router 和旧的 Pages Router,帮助你更好地理解 Next.js 的演进。