Next.js 是一个基于 React 的服务端渲染框架,它提供了很多开箱即用的功能,如自动路由、API 路由、静态生成、增量静态再生等。本文将带你一步步创建一个 Next.js 项目,并实现一个简单的 TodoList 功能。
🧱 安装 Next.js 项目
首先确保你的开发环境已经安装了 Node.js(推荐版本为 Node.js 18.18 或更高)。
接下来使用 create-next-app
创建一个新的 Next.js 项目:
npm i create-next-app@latest
npx create-next-app@latest nexy-app
在创建过程中,命令行会引导你选择以下配置项:
√ What is your project named? ... nexy-app
√ Would you like to use TypeScript? ... Yes
√ Would you like to use ESLint? ... Yes
√ Would you like to use Tailwind CSS? ... Yes
√ Would you like your code inside a `src/` directory? ... Yes
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to use Turbopack for `next dev`? ... No
√ Would you like to customize the import alias (`@/*` by default)? ... Yes
√ What import alias would you like configured? ... @/*
这些选项的作用:
选项 | 说明 |
---|---|
TypeScript | 启用 TypeScript 支持 |
ESLint | 添加代码规范支持 |
Tailwind CSS | 使用 Tailwind CSS 作为样式工具 |
src/ 目录 | 将代码结构放在 src 文件夹下 |
App Router | 使用 Next.js 13+ 推荐的 App Router 系统 |
Turbopack | 使用实验性的快速打包工具 |
导入别名 | 设置模块路径别名,方便引用 |
完成后,进入项目目录并运行开发服务器:
cd nexy-app
npm run dev
📁 Next.js 的文件系统路由机制
Next.js 13+ 引入了基于文件系统的路由系统(File-system based routing),这是其核心特性之一 。
基本规则如下:
- 每个
src/app
下的文件夹代表一个路由段。 - 文件夹中的
page.tsx
是该路由的页面组件。 - 特殊文件有特定用途:
layout.tsx
:共享布局loading.tsx
:加载状态组件error.tsx
:错误边界not-found.tsx
:404 页面
示例结构:
src/
└── app/
├── page.tsx → /
├── about/
│ └── page.tsx → /about
├── contact/
│ └── page.tsx → /contact
Next.js 会在构建时自动扫描 app
目录,根据目录结构生成对应的路由配置,无需手动注册 。
✅ 实现一个 TodoList 示例
下面我们将创建一个简单的 TodoList 页面,演示如何在 Next.js 中使用客户端组件和状态管理。
步骤一:创建页面文件
在 src/app
目录下新建一个 todo
文件夹,并在其内部创建 page.tsx
文件:
src/app/todo/page.tsx
步骤二:编写 TodoList 组件
"use client"; // 表示这是一个客户端组件
import React, { useState } from "react";
// 定义 Todo 项的类型
interface TodoItem {
id: number;
text: string;
completed: boolean;
}
export default function TodoPage() {
const [todos, setTodos] = useState<TodoItem[]>([]);
const [inputValue, setInputValue] = useState("");
const addTodo = (e: React.FormEvent) => {
e.preventDefault();
if (inputValue.trim() === "") return;
const newTodo: TodoItem = {
id: Date.now(),
text: inputValue.trim(),
completed: false,
};
setTodos([...todos, newTodo]);
setInputValue("");
};
const toggleTodo = (id: number) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
const deleteTodo = (id: number) => {
setTodos(todos.filter((todo) => todo.id !== id));
};
return (
<div className="min-h-screen p-8">
<div className="max-w-md mx-auto">
<h1 className="text-3xl font-bold mb-8 text-center">Todo List</h1>
{/* 添加 Todo 的表单 */}
<form onSubmit={addTodo} className="mb-8">
<div className="flex gap-2">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="添加新的待办事项..."
className="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
type="submit"
className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
添加
</button>
</div>
</form>
{/* Todo 列表 */}
<ul className="space-y-3">
{todos.map((todo) => (
<li
key={todo.id}
className="flex items-center justify-between p-4 bg-white rounded-lg shadow"
>
<div className="flex items-center gap-3">
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
className="w-5 h-5 text-blue-500 rounded focus:ring-blue-500"
/>
<span
className={`${
todo.completed
? "line-through text-gray-500"
: "text-gray-800"
}`}
>
{todo.text}
</span>
</div>
<button
onClick={() => deleteTodo(todo.id)}
className="text-red-500 hover:text-red-700 focus:outline-none"
>
删除
</button>
</li>
))}
</ul>
{/* 显示 Todo 统计信息 */}
{todos.length > 0 && (
<div className="mt-4 text-sm text-gray-500">
总计: {todos.length} 项 | 已完成:{" "}
{todos.filter((t) => t.completed).length} 项
</div>
)}
</div>
</div>
);
}
步骤三:访问页面
现在你可以访问 http://localhost:3000/todo 查看这个 TodoList 页面。
🌟 Next.js 的优势总结
- 自动路由:无需手动注册路由,基于文件结构自动生成。
- Server Components 和 Client Components 分离:提升性能和可维护性。
- 集成 Tailwind CSS:轻松构建现代 UI。
- 支持 TypeScript:提供更强的类型安全。
- SSG & SSR 支持:适合 SEO 友好型网站。
- Turbopack / Fast Refresh:更快的开发体验。