Next.js Router快速上手指南,掌握一半,项目开发事半功倍!

如果想看专栏的方式可以点击进入Next图册目实践

Next.js Router

大家好呀,这里是梦兽编程。今天分享的内容是Next.js非常重要的内容。它关系到Next.js的整个系统的运行。如果你有ThinkPHP3.2的开发经验,那这个Next.js 13的文件路由是非常容易理解的。它就是一个很典型的 MVC Web 开发架构。

本次的花瓣发现案例将以App Router 为例子。我们会在上次分享安装Next.js得到的项目目录如下:

shell 复制代码
├── app

│   ├── favicon.ico

│   ├── globals.css

│   ├── layout.tsx

│   └── page.tsx

├── next.config.js

├── package-lock.json

├── package.json

├── pnpm-lock.yaml

├── postcss.config.js

├── public

│   ├── next.svg

│   └── vercel.svg

├── tailwind.config.ts

└── tsconfig.json

而我们的 app 项目路径就是Next.js 13使用 App router 的文件目录。如果你想使用Page Router。你可以改成page文件夹。注意的page文件的运行文件不是page.tsx

app文件夹下我们可以看到有

shell 复制代码
├── app

│   ├── favicon.ico

│   ├── globals.css // 全局的css

│   ├── layout.tsx // 页面的layout布局

│   └── page.tsx // page 只要的内容

当然我们还可以可选一些可选的文件内容,一般来说我们用的比较多的是前面两个。如果你是需要自定义路由则可以添加route.tsx文件进行定义。next.jsapp router 中优先匹配route.tsx路由规则。

ps:page.tsxroute.tsx是不能共存的

  • layout Shared UI for a segment and its children

  • page Unique UI of a route and make routes publicly accessible

  • loading Loading UI for a segment and its children (类似 React 中的 Suspense 一样的用法)

  • not-found Not found UI for a segment and its children (没有匹配到路由的渲染页面可以理解成 404.html)

  • error Error UI for a segment and its children

  • global-error Global Error UI

  • route Server-side API endpoint

  • template Specialized re-rendered Layout UI (模版:可以理解成服务端渲染的组件,或者 C 语言中的宏,把公共的 HTML 渲染处理写在一起)

  • default Fallback UI for Parallel Routes (如果你有一些数据需要异步加载想做骨架子的时候可以用到它)

以上的机制在每一个"page"(页面)文件夹都可以写一份,如果不存在会读取父级

多级路由映射

有了这些基础概念以上的基本路由概念之后,我们就可以愉快的做一些"MVC"的 web 开发了。如果我们需要拥有和本次项目实践差不多路由https://huaban.com/discovery。在Next.js要如何实现呢?

1. 开发小技巧

如果你想偷懒快速生成代码可以安装ES7+React...的插件

我们只需要在 app 文件下新增一个discovery文件夹,并且新增page.tsx文件即可。

// 复制代码
├── discovery

│   └── page.tsx

├── favicon.ico

├── globals.css

├── layout.tsx

└── page.tsx

在浏览器输入 http://localhost:3000/discovery 即可看到我们进入"MVC" 模式下的 discovery 应用页面。

Next.js App Router 里的 Params 参数设置

1. 利用文件路由

在我们 React router 开发中经常会遇到这种路由http://localhost:3000/discovery/:id。在Next.js 13中应该如何实现这样的功能呢?

我们只需要在 discovery 文件夹下新增一个[id]文件夹目录同时新增page.tsx即可达到目的。这时候的文件目录将会变成以下结构:

shell 复制代码
├── [id]

│ └── page.tsx

└── page.tsx

我们如果需要获取params参数应该如何获取呢?

ts 复制代码
import React from "react";

  


function page({ params }: { params: { id: string } }) {

return <div>discovery Id is : {params.id}</div>;

}

  


export default page;

是的 mvc 架构就是这么简单粗暴,我们在浏览器中输入http://localhost:3000/discovery/rex可以得到以下结果

2. 多个参数我们要如何应对?

在上面的例子中,我们知道传统 web mvc 架构的粗暴处理方式,为什么现在的 web 框架都是使用 router map 做正则配置呢?如果我们遇到这么一个路由http://localhost:3000/discovery/:id/:pid/:cid,在这个路由中如果我们还是安装 mvc 文件路由的方式,我们和容易就写出多个文件夹嵌套文件路径。参数多了人都会奔溃!!!

当然在 next.js 文件路由中。还是友好的给我们提供了方案的。我们只需要修改我们的文件夹就好了,比如

shell 复制代码
// app 文件夹下新增demo 并且 [...slug]

.

├── demo

│ ├── [...slug]

│ │ └── page.tsx

│ └── page.tsx

主要这里我们多个参数获取的时候需要修改一下一下 page 的获取。需要在 slug 的属性下获取

ts 复制代码
import React from "react";

  


function page({ params }: { params: { slug: string[] } }) {

return <div>{params.slug.map((v) => v)}</div>;

}

  


export default page;

Next.js Rest Api 的处理

1. Rest Api 如何定义并响应

我们做服务端应用开发最基础的功能就是对业务进行增删改成,在 Next.js 中同样给我们提供一套 Rest Api 的机制。就是我们上面提到的router.tsx文件。一般来说我们会在app/api里面进行开发,因为上面有提及到route.(tsx|ts|jsx|js)是不能与page.(tsx|jsx)共存一个文件目录下的。

同样路由规格还是以 next.js 的 mvc 文件规则一样。如果我们需要开发一个http://localhost:3000/api/discovery。我们需要把我们的项目结构改成:

shell 复制代码
// app 文件夹下

.

├── api

│ └── discovery

│ └── route.ts

我们大致来看一下 route.ts 的大致模版

ts 复制代码
// 分别对应 http 协议请求中的 get post put delete head 和 options 请求协议

export async function GET(request: Request) {}

export async function POST(request: Request) {}

export async function PUT(request: Request) {}

export async function DELTE(request: Request) {}

export async function HEAD(request: Request) {}

export async function OPTIONS(request: Request) {}

在服务端我们需要进行内容的响应也就是 HTTP 请求中的 Response,在 Next.js 中next/server中提供 NextResponse 的静态类方法。它和 w3c 定义中的 Response 类型基本的实现。这里我们就以GET请求例子,进行讲解。比如我们需要响应一个{code:0}的 json 格式

ts 复制代码
import { NextResponse } from "next/server";

  


export async function GET(request: Request) {

return NextResponse.json({ code: 0 }); // 默认http 响应状态码 为200

// 可通过第二参数进行设置,它是一个 ResponseInit 的参数类型

// return NextResponse.json({ code: 0 }, { status: 500 });

}

2. 如何在 Rest Api 中获取Query和Param的参数类型还有Post的数据类型

这里以POST请求为例子,其他请求按需要获取

ts 复制代码
// 项目结构

// .

// ├── api

// │ └── discovery

// │ ├── [id]

// │ │ └── route.ts

import { NextResponse } from "next/server";

  


export async function POST(request: Request, params: { id: string }) {

// get query

const { searchParams } = new URL(request.url);

const allSearchParams = Object.fromEntries(searchParams);

// get params

const id = params.id;

// get formdata

const formdata = await request.formData();

const formdataJson = Object.fromEntries(formdata);

// get json 如果是 formdata 模式下不要请求

// const json = await request.json();

return NextResponse.json({

allSearchParams,

id,

formdataJson,

// json,

});

}

这个时候我们使用curl命令进行测试

txt 复制代码
curl -X POST -F "name=rex" "http://localhost:3000/api/discovery/rex?a=111"

# response json content

{"allSearchParams":{"a":"111"},"formdataJson":{"name":"rex"}}
txt 复制代码
curl -X POST -H "Content-Type: application/json" -d '{"name":"rex"}' "http://localhost:3000/api/discovery/rex?a=111"

  


{"allSearchParams":{"a":"111"},"json":{"name":"rex"}

3. 获取 cookeis 和 headers 操作

这里以PUT请求为例子

javascript 复制代码
export async function PUT(request: NextRequest) {

const cookies = request.cookies.getAll()

// 不推荐 在构建类似 hexo 静态页面(SSG)的时候会报错,说你依赖了cookies无法构建

// import {cookies} from 'next/headers'

// const cookie = cookies()

  


const headers = request.headers;

const ContentType = headers.get('Content-Type')

}

服务端的页面跳转 redirect 在中间件里面用的比较多

ts 复制代码
import { redirect } from 'next/navigation'

export async function GET(request: Request) {

redirect('https://nextjs.org/')

}

Middleware 中间件拦截器

Middleware 是我们服务端web开发里面非常重要的一个功能指标之一,你可以了解成Axios中的拦截器。在我们的开发过程中可以有一个地方进行处理。比如你的web应用需要进行Auth的校验可以使用Middleware进行一个入口全站应用,再比如你想每一个请求都进行一下日志打印的操作,这个时候中间件的出现真的是一杯美酒。

当然这个概念在其他web开发框架也有比如java spring boot,php laravel,node.js nest.js,golang gin。知道一个应用场景几乎其他语言的应用场景都会掌握只是语法上的区别和极端环境下的的问题了。

1. 我们在next.js中要如何使用Middleware

shell 复制代码
# 在app文件

.

...

├── ....

├── middleware.ts (添加)

中间件的具体内容

ts 复制代码
import { NextResponse } from "next/server";

import { NextRequest } from "next/server";

  


// This function can be marked `async` if using `await` inside

export async function middleware(request: NextRequest) {

const { pathname } = request.nextUrl;

// 比如我们对/api不做任何处理

if (!["/api"].some((prefix) => pathname.startsWith(prefix))) {

return NextResponse.next();

}

// 比如我们对 /demo 进行一下操作,如果没有权限的时候跳转到百度

if (["/demo"].some((prefix) => pathname.startsWith(prefix))) {

// handle someing

return NextResponse.redirect("http://www.baidu.com");

}

// 比如我们需要做一些日志操作的时候

// if (request.method === "POST") {

// console.log(await request.json());

// }

return NextResponse.next();

}

  


// See "Matching Paths" below to learn more

// 匹配的路由机制 除非你业务非常简单,要不不推荐使用

// export const config = {

// matcher: '/:path*',

// }

  

结语

这里是梦兽编程,本次的代码更新将会放在Github本次项目的Github连接中。

我的B站视频号更多视频动态。

以上就是Next.js路由的所有内容了,如果对你的学习有任何帮助记得给梦兽编程一个一件三连。

相关推荐
zqx_740 分钟前
随记 前端框架React的初步认识
前端·react.js·前端框架
coderWangbuer1 小时前
基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
spring boot·后端·sql
攸攸太上1 小时前
JMeter学习
java·后端·学习·jmeter·微服务
Kenny.志1 小时前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端
惜.己1 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
sky丶Mamba1 小时前
Spring Boot中获取application.yml中属性的几种方式
java·spring boot·后端
什么鬼昵称1 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色2 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2342 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河2 小时前
CSS总结
前端·css