Skip to content
第 143 / 250 章前端⏱ 10 分钟阅读

第 143 章:第一个 Next.js 应用

学习目标

  • 理解 App Router 目录结构
  • 掌握 layout.tsxpage.tsx
  • 创建第一个 React 组件
  • 理解 Server vs Client Components

一、项目结构

hello-react/
├── app/
│   ├── layout.tsx          # 根布局(必须)
│   ├── page.tsx            # 首页 /
│   └── globals.css
├── components/
├── public/
└── package.json

二、核心文件

2.1 layout.tsx(根布局)

tsx
// app/layout.tsx
import type { Metadata } from 'next';
import './globals.css';

export const metadata: Metadata = {
  title: '我的 Next.js 应用',
  description: '学习 React 18 + Next.js 14',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="zh-CN">
      <body className="antialiased">
        <header className="bg-blue-500 p-4 text-white">
          <h1>我的网站</h1>
        </header>
        <main className="container mx-auto p-4">
          {children}
        </main>
        <footer className="bg-gray-100 p-4 text-center">
          © 2026
        </footer>
      </body>
    </html>
  );
}

2.2 page.tsx(首页)

tsx
// app/page.tsx
export default function Home() {
  return (
    <div>
      <h2 className="text-3xl font-bold">欢迎来到 Next.js!</h2>
      <p className="mt-4">这是我的第一个页面。</p>
    </div>
  );
}

三、组件化拆分

tsx
// components/Greeting.tsx
interface GreetingProps {
  name: string;
  age?: number;
}

export function Greeting({ name, age = 18 }: GreetingProps) {
  return (
    <div className="rounded border p-4">
      <h3>你好,{name}!</h3>
      {age && <p>你今年 {age} 岁</p>}
    </div>
  );
}
tsx
// app/page.tsx
import { Greeting } from '@/components/Greeting';

export default function Home() {
  return (
    <div>
      <Greeting name="张三" />
      <Greeting name="李四" age={20} />
    </div>
  );
}

四、Server vs Client Components

Server Component(默认)

tsx
export default async function Page() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();
  return <div>{data.title}</div>;
}

Client Component

tsx
'use client';
import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      点击 {count} 次
    </button>
  );
}

五、添加新路由

app/
├── about/
│   ├── layout.tsx
│   └── page.tsx       ← 访问 /about
tsx
// app/about/page.tsx
export default function About() {
  return <h1>关于我们</h1>;
}

六、本章小结

文件作用
app/layout.tsx根布局
app/page.tsx首页
components/自定义组件
'use client'客户端组件指令

动手练习

  1. 修改 app/page.tsx 展示你的名字和日期
  2. 创建 app/about/page.tsx
  3. 创建 components/Card.tsx 接收 titlechildren

推荐阅读


下一章:第 144 章:JSX 语法详解

本站基于 VitePress 构建 · 由 Codebook 团队维护