掌握Next.js(三)– 路径和导航

本篇来学习Next.js的路径和导航。内容包括:

定义动态路径、访问路径和查询参数、创建布局、显示加载界面以及处理错误等。


路径概述

前面我们介绍过Next.js是通过文件系统进行路由的,比如之前的users。Next.js除查找page.tsx这个特定文件外,还查看其他特定文件,如下图。

layout.tsx用于定义通用的布局。

loading.tsx用于显示加载界面。

route.tsx用于建立APIs。

not-found.tsx用于显示找不到页面的错误。

error.tsx用于显示意外错误。

前面说过,page.tsx定义的组件可以被公共访问,其他文件则不会被访问到,这就给我们带了好处。到page.tsx越来越复杂时,我们将相关逻辑拆分到其他组件即可,拆分的组件与page.tsx并排放置,因为功能是相关联的,在同一文件夹下组织更合理。如碰到有些组件是要重用的,就将它放置在外部的components目录即可。


动态路径

如果要查看用户的详细信息,用到的URL可能是 /users/1、/users/2 之类的,这就用到动态路径。

动态路径就是将文件夹名称加上方括号,比如在/users目录下新建 [id]文件夹,这样就表示是动态路径,然后再添加page.tsx,获取参数。

然后我们访问 /users/1,就能动态展示页面了。

再进一步,类似这样的路径 /users/1/photos/2 ,该如何处理呢。

这里有2个参数,我们可以在[id] 目录下新建 photos目录,然后再新建带方括号的[photoId]目录,在其下放置page.tsx,然后进行相关参数的获取即可。注意目录[photoId]不能再命名为[id],因为上级已有同名的了。

页面展示:


多参数获取

有时候需要进行多参数获取。比如:

products/grocery/dairy/milk

grecery、dairy、milk都是传递过来的参数,如何获取?

使用前面的嵌套创建文件夹方式不太行了。我们使用前面加3点的文件夹命名方法实现:[…名称]。

访问页面如下。

这里还有一个小问题,如果我们不加参数,比如访问:

/products

将提示找不到页面的404错误。解决的方法是再套一层方括号:

[[…slug]]

这样访问 /products 就不会提示 404了。


访问查询字符串参数

有时需要获取查询字符串,比如

/products?sortOrder=name

加上searchParams属性即可获取。

查看页面能获取。

我们来做一个练习,之前的 /users 列出了 jsonplaceholder 的用户列表,现在要求的是点击Name就按 Name排序,点击 Email就按Email排序。

google搜索 “npm fast sort” 找到fast-sort库,安装下,排序时需要用到:

npm i fast-sort

users/page.tsx中添加获取sortOrder查询参数的代码。

再修改users/UsersTable.tsx。

完成后,点击表格标题就能进行排序。


布局

之前的我们提到在app目录下有一个layout.tsx文件,这个就是布局文件。

新建admin文件夹,再在其下新建layout.tsx文件,必须是layout小写,这是规定的。创建一个Props,传递children。我们的页面到时将动态替换掉children。

再创建page.tsx文件。

查看页面,发现page.tsx页面替换了layout.tsx定义的 children节点。

定义在app目录下的layout.tsx文件适用于全部页面。而在admin目录下的只对admin路径下的页面有效。

我们来做一个NavBar,使所有页面上都有导航条。

所有页面都有,肯定放在 app/layout.tsx上。为了不污染原生组件,我们拆分创建一个NavBar.tsx组件。

再在 app/layout.tsx调用。

再调整下global.css,比如body不要padding,h1标识在Tailwind不强调,我们重新设置。

我们打开任何一个网页,都有一个NavBar在顶部了。


导航

之前我们已用过导航用的Link组件了,对了Link,我们需要了解3点。

首先,Link只下载目标页面的内容,不会下载css,javascript等其他资源进行全加载。

其次,它会预加载在视图中的链接。

第三,它会将页面缓存到客户端,下次再访问时,不会再从服务器端获取。当然它只在一次会话中有效,重新刷新时还是需要从服务端下载的。


程序化导航

有时我们需要在点击按钮或提交表单时跳转到其他页面,这个就叫程序化导航。

先在 /users/page.tsx中添加 ‘New User’,这里用Link跳转。

再在 /users/new/page.tsx中添加按钮,按钮有onClick事件,需要转成客户端组件,利用 useRouter 的 push方法跳转。注意useRouter是从 next/navigation导入,不是 next/router。


显示加载界面

React有一个新组件叫 Suspense,用于显示加载界面,属性 fallback用于设置加载界面,可以是普通的HTML标记或组件。

在/users/page.tsx里,我们用Suspense将 UsersTable包起来,表示UsersTable数据未获得前用加载UI展示。

由于加载速度很快,显示加载界面一闪而过,我们可以使用 chrome的扩展 React Developer Tools查看,如果没装的话,可以Google搜索并安装。

查看服务器的响应,我们看到就是加载界面。有人会说,这对搜索引擎不友好啊因为看不到列表数据。

实际上这种说法是不对的,在响应加载界面后,服务端并未断开请求/响应的连接,后续服务端会继续响应用户列表数据给客户端,这个就叫做流媒体。

流媒体技术广泛应用于音频视频,但对于HTML,也是可以使用流媒体技术的。

在页面上我们可以多次使用Suspense将相关组件包起来使用。如果我们希望所有页面都有Suspense显示加载界面的话,有两种方法:

一是可以根路径的layout.tsx里的children包起来。二是在根路径添加loading.tsx文件。

我们将加载界面提升一个层次。使用DaisyUI展示。

访问daisyUI.com,查找 Loading组件,并复制合适的CSS代码到 loading.tsx文件中。

查看页面,加载界面变成Spinner了。


处理未找到页面错误

未找到页面时,Next.js会给出默认的404页面,我们可以自定义not-found.tsx文件实现404页面的定制。

在 根路径 /app 下新建not-found.tsx,自定义错误信息。

当碰到找不到页面时,就显示该页面。

在特定的页面可能需要定义特定的404页面,比如我们只有用户10个,如果查看第11个用户时,我们给出找不到用户的提示,而不是前面定义的找不页面的提示。

在app/users/[id]下新建 not-found.tsx,这个路径下的404页面就由它负责了。

稍微修改下 app/users/[id]/page.tsx,id超出10用户返回404。

访问 /users/11就会使用 users/[id]/not-found.tsx 。


处理意外错误

出现意外错误,我们也可自定义页面。

先故意写错 在users/UsersTable.tsx获取后端数据的API端点,模拟意外错误。

根路径 app 下创建 error.tsx文件。注意必须使用客户端组件。

访问 /users 就会显示 error.tsx的内容。

使用error页面,需要了解二点:

第一,我们可以在不同的层次使用 error页面,比如还可以在 /users 下新建error.tsx以处理特定路径的错误提示。当然大多数情况下,一个全局的error来捕捉意外错误就足够了。

第二,error.tsx不能捕捉到layout.tsx的错误,我们的示例layout.tsx非常简单,但实际场景有可能比较复杂是有可能出错的。可以创建另一个文件 global-error.tsx 来捕捉,当然该文件也必须是客户端组件。

在error页面,一般需要获取error信息,然后存入日志保存,比如好用的日志有 sentry,可以访问 https://sentry.io 了解相关知识。本示例我们简单打印到屏幕。

另外,在遇到错误后,有时要允许用户重试,可以获取reset属性处理。我们添加一个按钮,onClick调用reset函数,正因为有这些onClick的存在,所以error.tsx的组件必须要求是客户端组件。

reset 的使用要谨慎,确实需要才使用,否则用户的重试将产生太多的错误日志。

自定义的错误页面如下,开发环境下,还允许用户直接点按钮查看详细。


小结

本文介绍了Next.js的动态路径、访问路径和查询参数、创建布局、显示加载界面以及处理错误等相关知识,我们看到,在Next.js中,路径及导航使用极其方便,而功能依旧强大。

下一篇计划介绍API的构建。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注