3-2NextJs添加一个easy页面通过钩子hook实现一些easy功能
📁 项目结构与路由规划
my-next-demo/
├── app/
│ ├── (home)/ # 路由组,URL中不显示(home)
│ │ └── page.tsx # 默认入口页面,路径 /
│ ├── test/
│ │ └── page.tsx # 自定义路由页面,路径 /test
│ ├── globals.css # 全局样式
│ └── layout.tsx # 根布局
├── public/ # 静态资源
├── styles/ # 样式文件(可选)
└── package.json
🧩 1. 默认入口页面 (app/(home)/page.tsx)
路由组 (home) 不会影响URL路径,该页面将作为网站首页。
// app/(home)/page.tsx
export default function HomePage() {
return (
);
}
访问 http://localhost:3000 即可看到此页面。
⚙️ 2. 自定义路由页面 (app/test/page.tsx)
这个页面将展示如何使用 React Hook (useState) 来管理状态,并包含一个交互按钮。
// app/test/page.tsx
‘use client’; // 由于使用了 useState,必须声明为客户端组件
import { useState, FC } from ‘react’;
import clsx from ‘clsx’; // 用于合并classNames
import Button from ‘@/components/Button’; // 假设有一个自定义Button组件
import $styles from ‘./style.module.css’; // 模块化CSS
const TestDemo: FC = () => {
// 使用 useState Hook 声明一个状态变量count和更新函数setCount,初始值为1
const [count, setCount] = useState(1);
return (
<div className={clsx($styles.container, 'w-[20rem]')}>
<h2 className="text-center">Hook Test</h2>
{/* 条件渲染计数显示 */}
{<p className="text-center py-5">{count}</p>}
<div className="flex justify-around">
<Button onClick={() => setCount(count + 1)} type="dashed">
Add
</Button>
{/* 可以添加更多按钮,例如减少计数 */}
<Button onClick={() => setCount(count - 1)} type="dashed">
Decrease
</Button>
</div>
</div>
);
};
export default TestDemo;
🔧 3. 补充说明与关键文件
• 布局文件 (app/layout.tsx):此文件为所有页面提供根布局,确保样式和脚本一致。
// app/layout.tsx
import type { Metadata } from ‘next’;
import ‘./globals.css’; // 导入全局样式
export const metadata: Metadata = {
title: 'My Next.js Demo',
description: 'A demo Next.js application with routing',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
• 全局样式 (app/globals.css):可以在这里定义一些基础样式或导入Tailwind CSS等框架。
/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
• CSS模块 (app/test/style.module.css):为TestDemo组件提供局部样式。
/* app/test/style.module.css */
.container {
@apply bg-neutral-100/40 shadow-black/20 backdrop-blur-sm shadow-md rounded-md p-5 m-5 min-w-[20rem];
}
• 自定义按钮组件 (components/Button.tsx):一个简单的可复用按钮。
// components/Button.tsx
‘use client’;
import { FC, ButtonHTMLAttributes } from 'react';
import clsx from 'clsx';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'dashed' | 'text';
}
const Button: FC<ButtonProps> = ({
className,
children,
variant = 'primary',
...props
}) => {
const baseClasses = 'px-4 py-2 rounded focus:outline-none transition-colors';
const variantClasses = {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
dashed: 'border border-dashed border-gray-400 text-gray-700 hover:bg-gray-100',
text: 'text-blue-500 hover:underline',
};
return (
<button
className={clsx(baseClasses, variantClasses[variant], className)}
{...props}
>
{children}
</button>
);
};
export default Button;
🚀 4. 运行与访问
-
启动开发服务器:
npm run dev或
yarn dev
或
pnpm dev
-
访问页面:
首页: http://localhost:3000
测试页面: http://localhost:3000/test
💎 核心概念回顾
通过这个例子,你可以了解到Next.js中几个重要的概念:
- App Router: Next.js 13+ 推荐使用的基于 app 目录的路由系统。
- 路由组(Route Groups): 使用 (folderName) 的形式创建路由组,不会体现在URL路径中,仅用于组织代码。
- 文件即路由: 在 app 目录下,page.tsx 是每个路由的页面组件。文件夹名(路由组除外)即路由路径。
- 客户端组件: 需要交互性(如使用 useState, useEffect)的组件必须在文件顶部添加 ‘use client’ 指令。
- 服务器端组件: 默认情况下,app 目录中的组件是React服务器组件(RSC),渲染工作在服务器端进行。这有利于性能和SEO。