Skip to content

Next.js基础部分

基于文件路由的机制

静态路由

Next.js 在构建时会自动查找根目录的 pages 文件夹,pages 文件夹中 js 文件对应渲染的 React 组件,就是 js 文件内 export default 导出的组件。

动态路由

动态路由使用中括号 [variable].js 作为文件名,其中 variable 会映射成 URL query 的变量名称,在 React 中可以通过 useRouter 获取路由信息:

js
import {useRouter} from 'next/router'

export default function PortfolioDemo() {
    const router = useRouter();
    console.log(router.pathname);
    console.log(router.query);

    return <>PortfolioDemo</>
}

在匹配 URL 时,静态路由优先权大于动态路由。

[...slug] 捕获blog之后的所有路径,并且作为slug数组的元素

router.push

在代码中,如果需要触发导航逻辑,可以使用 router.push 方法

js
import {useRouter} from 'next/router'

export default function PortfolioDemo() {
    const router = useRouter();

		const myFunc = () => {
	    router.push("[url]");
	  }

    return <>PortfolioDemo</>
}

页面(Page)

为了保证路由可以被访问,需要创建一个特殊的名为page.js 的文件

布局(Layout)

布局是指多个页面共享的 UI。在导航的时候,布局会保留状态、保持可交互性并且不会重新渲染,比如用来实现后台管理系统的侧边导航栏。

定义一个布局,需要新建一个名为 layout.js 的文件,该文件默认导出一个 React 组件,该组件应接收一个 children prop,chidren 表示子布局(如果有的话)或者子页面。

同一文件夹下如果有 layout.jspage.js,page 会作为 children 参数传入 layout。换句话说,layout 会包裹同层级的 page。 布局是支持嵌套的

根布局(Root Layout)

布局支持嵌套,最顶层的布局我们称之为根布局(Root Layout),也就是 app/layout.js 它会应用于所有的路由

注意:

  1. app 目录必须包含根布局,也就是 app/layout.js 这个文件是必需的。
  2. 根布局必须包含 html 和 body标签,其他布局不能包含这些标签。如果要更改这些标签,不推荐直接修改
  3. 可以使用路由组创建多个根布局。
  4. 默认根布局是服务端组件,且不能设置为客户端组件。

模版(template)

模板类似于布局,它也会传入每个子布局或者页面。但不会像布局那样维持状态。

模板在路由切换时会为每一个 children 创建一个实例。这就意味着当用户在共享一个模板的路由间跳转的时候,将会重新挂载组件实例,重新创建 DOM 元素,不保留状态。

定义一个模板,需要新建一个名为 template.js 的文件,该文件默认导出一个 React 组件,该组件接收一个 children prop

加载界面(Loading UI)

App Router 提供了用于展示加载界面的 loading.js, 这个功能的实现借助了 React 的Suspense API。它实现的效果就是当发生路由变化的时候,立刻展示 fallback UI,等加载完成后,展示数据。

关于 Suspense ——在哪里控制关闭 fallback UI 的呢?

简单的来说,ProfilePage 会 throw 一个数据加载的 promise,Suspense 会捕获这个 promise,追加一个 then 函数,then 函数中实现替换 fallback UI 。当数据加载完毕,promise 进入 resolve 状态,then 函数执行,于是更新替换 fallback UI。

所以加载界面的实现关键在于 page.js 导出了一个 async 函数

loading.js 的实现原理是将 page.js 和下面的 children<Suspense> 包裹。因为 page.js 导出一个 async 函数,Suspense 得以捕获数据加载的 promise,借此实现了 loading 组件的关闭。

404

pages 文件夹下创建特殊文件 404.js或者not-found.js,Next.js 将会在返回 404 错误时,自动加载组件。

相当于用户可以自定义 404 页面

静态文件

根目录 public 目录下放静态文件,Next.js 会自动处理,放在这个文件夹外的静态文件是无法获取到的

链接与导航

基础使用

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

使用 useRouter Hook(客户端组件)

这是 Next.js 提供的用于更改路由的 hook

基础使用

js
'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 函数(服务端组件)

客户端组件使用 useRouter hook,服务端组件则可以直接使用 redirect 函数,这也是 Next.js 提供的 API

基础使用

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

使用浏览器原生 History API

也可以使用浏览器原生的 window.history.pushStatewindow.history.replaceState 方法更新浏览器的历史记录堆栈。通常与 usePathname(获取路径名的 hook) 和 useSearchParams(获取页面参数的 hook) 一起使用。

上次更新于: