likes
comments
collection
share

Next.js 中不可忽视的路由系统

作者站长头像
站长
· 阅读数 51

前言

路由是支撑项目的基石,路由的存在,让页面之间可以实现跳转,传参,甚至是页面的展示都离不开路由。

在 Next.js v13 版本中引入了新的路由模式 App Router,它支持共享布局、嵌套路由、错误处理等,相比于之前的 Pages Router,App Router 制定了更加完善的规范,使代码更好被组织和管理。

定义路由

Next.js 中使用的是基于文件系统的路由,也就是使用文件夹来定义路由,每次定义的文件夹名称就会映射到对应的 URL 中。

Next.js 中不可忽视的路由系统

要想使 URL 可以访问,必须在其对应的文件夹中存在 page.js 文件,如下图所示,/dashboard/analytics 路由是不可访问的,因为在 analytics 文件夹下不存在 page.js 文件。

其中 page.js 文件是 Next.js 约定的,必须为这个名称,否则不识别,作用是为路由创建用户界面,即 UI。

Next.js 中不可忽视的路由系统

链接与导航

使用 Link 组件

<Link> 组件是 Next.js 中的一个内置组件,是官方推荐的方式,可以直接在 next/link 中导入并使用。

import Link from 'next/link'  
  
export default function Page() {  
  return <Link href="/dashboard">Dashboard</Link>  
}

使用 useRouter 钩子

使用 useRouter 钩子可以让我们以编程式的方式实现导航,直接在 next/navigation 中引入。

值得注意的是,在使用 useRouter 的组件中需要在最顶部书写 use client 用来表示这是一个客户端组件。

'use client'  
  
import { useRouter } from 'next/navigation'  
  
export default function Page() {  
  const router = useRouter()  
  
  return (  
    <button type="button" onClick={() => router.push('/dashboard')}>  
      Dashboard  
    </button>  
  )  
}

使用 redirect 功能

可以在服务端组件使用 redirect 来实现导航,

import { redirect } from 'next/navigation'  
  
async function fetchTeam(id: string) {  
  const res = await fetch('https://...')  
  if (!res.ok) return undefined  
  return res.json()  
}  
  
export default async function Profile({ params }: { params: { id: string } }) {  
  const team = await fetchTeam(params.id)  
  if (!team) {  
    redirect('/login')  
  }
  // ...  
}

路由组

概念

在 Next.js 的 app 目录中,嵌套文件夹会映射到 URL 路径,Next.js 中有一个路由组的概念,这会帮助我们把文件夹标记为路由组,可以用来防止此文件夹包含在路由的 URL 路径中。

路由组的使用方式:通过将文件夹的名称括在括号中来创建路由组:(folderName)

作用

组织路由而不影响 URL 路径

下图中的 (marketing)(shop) 这两个文件夹,这表示创建了两个路由组,在 URL 中将会省略括号中的文件夹,映射到 URL 中的路径就是 /about/blog

从而可以使我们在不影响 URL 的情况下组织路由将相关路由保存在一起。

Next.js 中不可忽视的路由系统

虽然 (marketing)(shop) 这两个路由组中的路由共享相同的 URL 层次结构,我们仍然可以在其文件夹中创建 layout.js 文件,实现不同的路由组能够拥有不同的布局。

Next.js 中不可忽视的路由系统

选择特定的路由到布局中

例如,我们可以创建一个新的路由组 (shop),可以将路由 accountcart 放置到能够共享相同布局的路由组 (shop) 中,而路由组之外的 checkout 路由将不会共享路由组中的布局。

Next.js 中不可忽视的路由系统

创建多个根布局

创建多个根布局,我们可以直接在每个路由组中创建 layout.js 文件,值得注意的是,还需要删除顶层的 layout.js 文件,这有助于我们根据不同的业务需求渲染不同的 UI 组件。

因为顶层的 layout.js 文件被删除,因此还需要将 <html> 和 <body> 标签添加到每个根布局中。

Next.js 中不可忽视的路由系统

值得注意的是,包含路由组的路由不应解析为与其他路由相同的 URL 路径。

动态路由

概念

我们可以通过将文件夹的名称括在方括号中创建动态段 [folderName],如 [id][slug] 等,动态段将会作为 params 属性传递给 layoutpage 等函数中。

示例

例如,博客路由为 app/blog/[slug]/page.js,其中 [slug] 就可以表示为博客帖子的动态分段。

export default function Page({ params }) {  
  return <div>My Post: {params.slug}</div>  
}

当我们访问 /blog/a 的时候,params 对应的值为 { slug: 'a' }

当我们访问 /blog/b 的时候,params 对应的值为 { slug: 'b' }

当我们访问 /blog/c 的时候,params 对应的值为 { slug: 'c' }

还有一点需要注意,在括号 [...folderName] 内添加省略号,可以扩展动态段以捕获所有后续段。

例如,博客路由为 app/shop/[...slug]/page.js,相比于 [slug] 这种形式,[...slug] 可以匹配所有的参数。可以匹配 /shop/clothes/shop/clothes/tops/shop/clothes/tops/t-shirts 等。

当我们访问 /shop/a 的时候,params 对应的值为 { slug: ['a'] }

当我们访问 /shop/a/b 的时候,params 对应的值为 { slug: ['a', 'b'] }

当我们访问 /shop/a/b/c 的时候,params 对应的值为 { slug: ['a', 'b', 'c'] }

平行路由

平行路由允许我们有条件的渲染同一布局中的一个或者多个页面,例如,使用平行路由可以同时渲染下图中的两个页面,team 和 analytics 页面。

Next.js 中不可忽视的路由系统

平行路由是使用命令插槽创建的,插槽是按照 @folder 约定定义的,例如,下图中的文件结构中定义了两个插槽 @analytics 和 @team

Next.js 中不可忽视的路由系统

插槽会作为属性传递给共享的父布局,例如上图的文件结构中,app/layout.js 布局组件会接受两个传入的插槽属性 @analytics 和 @team,与 children 属性并行渲染。

export default function Layout({ children, team, analytics }) {
  return (
    <>
      {children}
      {team}
      {analytics}
    </>
  )
}

值得注意的是,平行路由和路由组一样,不会影响 URL。例如,/@analytics/views 文件夹所对应的真实的 URL 地址为 /views

而实际上 children 是一个隐式的插槽,意味着 app/page.js 相当于 app/@children/page.js,因此不需要映射到文件夹。

总结

Next.js 中的路由系统,相比于直接使用 React 开发,从头配置路由便捷很多,同时 Next.js 也帮我们在内部封装了许多功能,就基于文件系统的路由本身来说,大大提高开发者的工作效率,文件即路由,免去那些繁杂的配置,像路由组、平行路由这些出现在 Next.js 中的新概念,更是让我们认识到 Next.js 的强大。

转载自:https://juejin.cn/post/7371641316114464804
评论
请登录