Next.js第三章(App Router)

Next.js 路由概览

Next.js 使用基于文件系统的路由,这意味着文件和文件夹的结构直接决定了应用的路由结构。

基于文件系统的路由

我们只需要创建对应的文件和文件夹,Next.js 会自动生成对应的路由。

在 Next.js 中,每个文件夹代表一个路由段,映射到 URL 段:

page

bash 复制代码
app/
├── page.tsx               # /
├── about/
│   └── page.tsx           # /about
├── blog/test
│        └── page.tsx      # /blog/test
└── contact/
    └── page.tsx           # /contact

layout && template

layout(布局) 布局是多个页面共享UI,例如导航栏、侧边栏、底部等。

template(模板) 基本功能跟布局一样,只是不会保存状态

布局和模板的特点就是:

  • 多个布局可以嵌套
  • 布局会保存状态 / 模板不会保存状态
  • 根布局(必须存在)
  • 如果布局和模板同时存在,则布局会优先于模板 layout->template-page

目录结构如下:

txt 复制代码
app
└─ blog
   ├─ layout.tsx
   ├─ template.tsx
   ├─ a
   │  └─ page.tsx
   └─ b
      └─ page.tsx

app/blog/layout.tsx

tsx 复制代码
'use client' //需要交互的地方要改为客户端组件 默认是服务端组件
import { useState } from "react"
export default function BlogLayout({ children }: { children: React.ReactNode }) {
    const [count, setCount] = useState(0)
    return (
        <div>
            <h1>Blog 布局组件</h1>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <h1>数量: {count}</h1>
            <hr />
            {children}
        </div>
    )
}

app/blog/template.tsx

tsx 复制代码
'use client' //需要交互的地方要改为客户端组件 默认是服务端组件
import { useState } from "react"
export default function BlogTemplate({ children }: { children: React.ReactNode }) {
    const [count, setCount] = useState(0)
    return (
        <div>
            <h1>Blog Template</h1>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <h1>数量: {count}</h1>
            <hr />
            {children}
        </div>
    )
}

app/blog/a/page.tsx

tsx 复制代码
import Link from "next/link"
export default function APage() {
    return (
        <div>
            <h1>A Page</h1>
            <Link href="/blog/b">跳转B</Link>
        </div>
    )
}

app/blog/b/page.tsx

tsx 复制代码
import Link from "next/link"
export default function BPage() {
    return (
        <div>
            <h1>B Page</h1>
            <Link href="/blog/a">跳转A</Link>
        </div>
    )
}

loading(加载)

Next.js的loading是借助了Suspense实现的,Suspense的具体用法请参考Suspense 组件

app/blog/loading.tsx

tsx 复制代码
export default function Loading() {
    return (
        <div>
            <h1>Loading...</h1>
        </div>
    )
}

app/blog/a/page.tsx

tsx 复制代码
import Link from "next/link"
const getData = async () => {
  //触发异步会自动跳转到loading组件 异步结束正常返回页面
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("数据")
    }, 5000)
  })
}
export default async function APage() {
    const data = await getData()
    console.log(data)
    return (
        <div>
            <h1>A Page</h1>
            <Link href="/blog/b">跳转B</Link>
        </div>
    )
}

error(错误)

Next.js的error是借助了Error Boundary实现的。

app/blog/error.tsx

tsx 复制代码
'use client' //错误组件必须是客户端组件
export default function Error() {
    return (
        <div>
            <h1>Error</h1>
        </div>
    )
}

app/blog/a/page.tsx

tsx 复制代码
import Link from "next/link"
export default async function APage() {
   //遇到异常会自动跳转到error组件
    throw new Error("错误")
    return (
        <div>
            <h1>A Page</h1>
            <Link href="/blog/b">跳转B</Link>
        </div>
    )
}

not-found(404)

其实Next.js 默认会生成一个404页面,但我们可能自定义404页面,只需要在app目录下创建一个not-found.tsx文件即可

app/not-found.tsx

tsx 复制代码
export default function NotFound() {
    return (
        <div>
            <h1>404 Page</h1>
        </div>
    )
}

预计学习时间 : 20 分钟
难度级别: 初级 🟢

相关推荐
濮水大叔26 分钟前
不必把 Vue3 写成“麻花”:从状态碎片到对象协作,重新理解 Zova 的前端心智模型
前端·typescript·vue3·ioc·tsx·zova
Vuji1 小时前
MCP: 一条 tool 调用链路的旅程
前端·人工智能
万少2 小时前
DeepSeek-V4-Flash 正式版上线了,但这 3 个坑我帮你提前踩了
前端·javascript·后端
明月_清风2 小时前
🚀 Palantir Foundry 本体论实战:当 Ontology 从"知识图谱"进化为"企业操作系统"
前端·后端
驳是2 小时前
入坑 Nginx,看这一篇就够了
前端
宁风NF2 小时前
JavaScript:网络请求与前端通信
开发语言·前端·javascript·网络·学习·ecmascript
明月_清风2 小时前
从概念到代码:用 Ontology 构建你的第一个知识图谱
前端·后端
程序员黑豆3 小时前
鸿蒙应用开发:AppStorage 全局状态存储用法教程
前端·harmonyos
猫猫不是喵喵.3 小时前
Vue3 中 computed 计算属性与 watch、watchEffect 监听
前端·javascript·vue.js
En^_^Joy3 小时前
Vue项目创建与入口配置全攻略
前端·vue.js·arcgis