NextJS: 内置组件及自动路由

18589
2022/11/17 20:30:11

NextJS 既然是 React 的框架,自然提供了一些内置组件来扩展 React。本章将介绍几个常用的 NextJS 内置组件,同时也将介绍 NextJS 的路由系统。

  • NextJS 使用的是自己实现的路由系统,而不是在 React 课程里说的那个 react-router。有关 NextJS 的路由将会在本章后面部分详细讲述。
  • 本章讲的组件都是 NextJS 内置的,不要和其它第三方提供的组件产生混淆

Head 组件

Head 组件什么鬼?HTML 里面的 <head>。恭喜你,答对了。我们先来回顾一下,上一章中“静态网站生成”最后构建并生成出来的HTML:(为了便于查看,这里进行了格式化。你如果要纠结原始版本,请回去上一章查看)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <meta name="next-head-count" content="2" />
    <link
      rel="preload"
      href="/_next/static/css/ef46db3751d8e999.css"
      as="style"
    />
    <link
      rel="stylesheet"
      href="/_next/static/css/ef46db3751d8e999.css"
      data-n-g=""
    />
    <noscript data-n-css=""></noscript>
    <script
      defer=""
      nomodule=""
      src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"
    ></script>
    <script
      src="/_next/static/chunks/webpack-8fa1640cc84ba8fe.js"
      defer=""
    ></script>
    <script
      src="/_next/static/chunks/framework-8c5acb0054140387.js"
      defer=""
    ></script>
    <script
      src="/_next/static/chunks/main-a15ee65a2f1e1948.js"
      defer=""
    ></script>
    <script
      src="/_next/static/chunks/pages/_app-2398585b21d2d8c8.js"
      defer=""
    ></script>
    <script
      src="/_next/static/chunks/pages/index-4c6abd58992a79df.js"
      defer=""
    ></script>
    <script
      src="/_next/static/uuuuuuuuuuuuuuuuuuuuu/_buildManifest.js"
      defer=""
    ></script>
    <script
      src="/_next/static/uuuuuuuuuuuuuuuuuuuuu/_ssgManifest.js"
      defer=""
    ></script>
  </head>
  <body>
    <div id="__next">
      <div>
        <h1>用户列表</h1>
        <ul>
          <li>
            ID:
            <!-- -->1<!-- -->, 姓名:
            <!-- -->axum中文网1
          </li>
          <li>
            ID:
            <!-- -->2<!-- -->, 姓名:
            <!-- -->axum中文网2
          </li>
          <li>
            ID:
            <!-- -->3<!-- -->, 姓名:
            <!-- -->axum中文网3
          </li>
          <li>
            ID:
            <!-- -->4<!-- -->, 姓名:
            <!-- -->axum中文网4
          </li>
          <li>
            ID:
            <!-- -->5<!-- -->, 姓名:
            <!-- -->axum中文网5
          </li>
          <li>
            ID:
            <!-- -->6<!-- -->, 姓名:
            <!-- -->axum中文网6
          </li>
        </ul>
      </div>
    </div>
    <script id="__NEXT_DATA__" type="application/json">
      {
        "props": { "pageProps": {} },
        "page": "/",
        "query": {},
        "buildId": "uuuuuuuuuuuuuuuuuuuuu",
        "nextExport": true,
        "autoExport": true,
        "isFallback": false,
        "scriptLoader": []
      }
    </script>
  </body>
</html>

有点长,但问题不大,请你检查一下,上面这个由 NextJS 生成的最终代码里,是不是:

  • 缺少了 <title>
  • 缺少了响应式布局最关键的 <meta name="viewport" content="width=device-width, initial-scale=1">(当然,NextJS提供了viewport,只是不适合响应式布局)

Head 组件就是为了让你有自定义 HTML <head> 的能力。

import Head from 'next/head';

export default function Home() {
  return (
    <>
      <Head>
        <title>AXUM中文网</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
      </Head>
      <h1>你好,axum.rs —— 来自 Next.js 的问候</h1>
    </>
  );
}

  • import Head from 'next/head':导入 Head 组件

  • Head 组件中,加上我们需要的内容:

    <Head>
      <title>AXUM中文网</title>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
    </Head>
    

本节代码:axum-rs-next-head

Link 组件

NextJS 的 Link 组件,就是用来创建超链接——用来创建组件之间通过路由跳转的超链接。也就是说,如果不是为了组件之间的路由跳转,不要使用它,而是直接使用 HTML 的 <a>

它的用法和 <a> 非常像:

<Link href="路由">文字</Link>

Image 组件

用来加载图片。你或许会说,图片而已用<img> 不香吗?Image 组件底层确实是使用 <img> 标签,而且用法和 <img> 也非常像。但它提供了增强功能:图片的懒加载功能。

在加载一张大图片的时候,这个增强功能非常有用,它会先呈现该图片的低像素版本,同时在后台异步获取原始图片,等到原始图片完全获取后,就使用原始图片替换低像素版本——这一切都是由nextjs自动完成的,你不需要手动提供低像素图片,你也不需要写任何代码实现这种功能。

但它有些限制:

  • 静态网站生成模式下,无法工作。就是说,它只在客户端渲染和服务端渲染时才有用
  • 它需要通过 heightwidth 属性来指定高度和宽度(可以通过使用fill来规避)。这一点让 tailwind 很不爽,因为 tailwind 都是用 CSS 的类来控制的

所以它的用法是:

<Image src="图片" alt="替换文本" width="宽度" height="高度" />

<Image src="图片" alt="替换文本" fill />

NextJS 的路由系统

我们先来回答开篇说的问题:为什么 NextJS 不使用 react-router?你要明确的是:react-router 也是第三方提供的组件,并不是 React 内置的。身为 React 的框架,NextJS 自然有选择它要使用哪个路由系统的权力——更重要的是,它完全可以自己实现路由系统。事实上,NextJS 的路由系统非常厉害,根本没有理由使用 react-router 等第三方路由系统。

静态自动路由

NextJS 的路由系统是最值得称赞的,它实现了自动路由功能——它会自动把pages下面的组件转换为路由!

比如有以下文件结构:

- pages
 - about.js
 - index.js
 - users
 	- index.js
 	- profile.js
 	- settings.js

NextJS 会进行自动路由:

页面组件自动路由
index.js/
users/index.js/users
users/profile.js/users/profile
users/settings.js/users/settings
about.js/about

除以上面这些与文件的目录结构一一对应的静态自动路由,NextJS 还支持动态自动路由。

动态自动路由

诸如 /news/:id/topic/:subject/:slug 这种动态路由,NextJS 是如何进行自动路由的呢?——答案是特殊的文件/目录名。

先来看 /news/:id,要实现 id 这个参数的动态路由,只需要将其页面组件的文件名改为 [id].jsx

- pages
	- news
		- [id].js

同理,/topic/:subject/:slug 就可以这样:

- pages
	- topic
		- [subject]
			- [slug].jsx

又比如:/blog/cate-:name/2022/11-:day 可以这样:

- pages
	- blog
		- cate-[name]
			- 2022
				- 11-[day].jsx

好了,理论知识至此结束,我们将在下一章使用目前所学的 NextJS 整合起来,实现一个稍微复杂的案例。撸起袖子准备大干一场吧!