Next.js 有两套路由方案:
1、Using App Router
2、Using Pages Router
Pages Router 是以前的方案,戒指到目前最新版本(v14.1.4)的脚手架安装,已经默认采用App Router构建项目了,但两套方案均可用于开发项目。
项目架构对比:
App Router
Pages Router
从 Pages 更新到 App 的 原因主要有以下两点:
(1)Pages 下每个文件都会被当成路由,不符合开发习惯
(2)App架构新增了布局(layout)、模版(template)、加载状态(loading)、错误处理(error)、404(not-found)等文件,为项目开发提供了一套规范。
(注意:App Router 和 Pages Router 是可以共存的,但是同时存在的情况下 App Router 优先级会大于 Pages Router)
定义路由
Next.js 的路由与文件路径形成映射关系,基于这个特点,我们不必再像使用 react 那样要单独定义一个路由表了
映射关系如下,只需在路由后加上页面 page.js :
/ => app/page.js
/dashboard => app/dashboard/page.js
/dashboard/setting => app/dashboard/setting/page.js
定义布局(layout)
布局文件是多个页面的共享UI,在导航的时候,布局会保留状态,保持可交互性并不会被重新渲染。
在页面上的呈现:
同一文件夹下,如果有 page.js 和 layout.js , page.js 会作为 children 传入 layout.js ,即 layout 包裹 page
同时 layout 是支持嵌套的,验证如下:
(当访问/dashboard/setting时,是去找setting下的page.js,与路径途中其他 page 无关)
根布局:app文件夹下的布局。它的特点是:
1、一定会有 2、必有 html 和 body 3、默认为服务器组件且不可以通过'use client'设置为客户端组件 4、借助路由组可以创建多个根布局。
定义模版(template)
同级下,layout、template、page 的关系:layout 包裹 template,template 包裹 page
模版和布局的区别在于,模版不会像布局那样维持状态,挡在共享模版内进行路由跳转是,将会重新挂载组件实例
(想要在页面中使用 Link、useState等,需要在页面中声明 'use client' 因为 App Router 默认为服务端渲染组件)
定义加载页面(loading)
类似于 React 中的
<Suspense fallback={<Spinner>}>
<profilepages />
</Suspense />
用法如下:
page.js 中
loading.js 中
原理:loading 用 <Suspense> 把 page 和 promise 包裹住,当Suspense 捕获到 promise(可以用aysnc 和 use函数获取(React的use函数,用于读取promise或者context的值)) 返回的数据时,关闭 fallback
错误处理(error)
page.js
error.js
这里的 error,reset 使用固定写法, reset 用来重新加载渲染组件
值得注意的是,同级下的文件包裹关系是这样的:
同层级下的 error 只能捕获到同层级的 page 的错误,对于同层级中 layout 和 template 的错误只能寻求上一层级的 error 来处理。对于顶级 app 中的layout 和 template ,Next.js 提供了一个 global-error 来处理。(global-error 和 app下的 error 没影响,两者可以同时存在)
定义404(not-found)
触发 not-found 的情况:
1、路由不匹配
2、由 notFound() 函数触发
(import { notFound } from 'next/navigation')