杨乐乐
Never too late

Follow

Never too late

Follow
NextJS Tutorial —Part 1

NextJS Tutorial —Part 1

The React Framework for production — Next.js Docs

杨乐乐's photo
杨乐乐
·Dec 6, 2022·

3 min read

Table of contents

第一次了解到 Next.js 是在开源项目 nextjs-notion-starter-kit,同步也是用这个项目搭建了一个基于 notion 的博客平台并且部署到了 vercel 上。以及最近经常看到 Youtube 上很多前端的项目都是基于 next.js 做的。所以有必要学习一下这个框架。 通过 Next.js 官方文档的阅读,可以看到其中有很多的特性,内容丰富、功能强大,简化优化开发的过程。文章包括以下部分:

  • Project Structure

  • Router

  • Navigation

  • Pre-rendering

  • Data Fetching

  • API Route

  • Styling

  • Image

  • Typescript

What is Next.js

The React Framework for production

React

  • 不太可能创建一个功能丰富的应用程序,用来部署到生产环境上

  • React 是一个用于构建用户界面的库

  • 需要去为应用的其他特性如路由、样式、权限等再去添加一些额外的内容

Next.js

  • 一个使用 React 构建用户界面的包

  • 自动加载了很多的特性帮助你构建一个丰富的应用程序。特性包含路由、样式、权限、bundle的优化等

  • 不需要安装额外的包,Next.js提供了一切

  • 为了实现上述特性,需要遵循一些意见和惯例

Why learn Next.js

Next.js 简化了构建一个生产环境的 React 应用

  1. File based routing - 基于文件的路由

  2. Pre-rendering - 预渲染

  3. API 路由

  4. 支持 CSS modules

  5. Authentication - 认证

  6. Dev and Prod build system - 开发和生产构建系统

Install Next.js App

可以使用下面的命令安装 Next.js 应用

npx create-next-app@latest --typescript

或者查看官方文档其他方式

Project Structure

需注意的是在 Next.js 中 pages 文件夹下的文件会自动生成路由,这部分会在下面介绍到。项目其他目录结构与别的脚手架没有什么大的不同

Route

在 React 应用中使用路由

  • 需要安装第三方包

  • 需要手动写文件去配置路由

  • 每一个路由、每一个组件、都需要去配置路由的属性,比较麻烦

在 Next.js 应用中使用路由

  • 基于文件系统的路由机制

  • 当在项目中的 pages 目录下添加了一个文件,就会自动的变成一个可用的路由

  • 通过将文件名和嵌套文件夹结构混合和匹配,几乎可以定义最常见的路由模式

Routing with pages

NextJS 有个一个基于文件系统的路由器,建立在 pages 文件夹的概念上

当一个文件被添加到 pages 目录下时,就会自动相对应的生成可使用的路由

Scenario 1 root router

只需将 pages → index.tsx 中的内容修改为 Home Page 即可

Scenario 2 basic router

实现方式有两种

  • pages 目录下创建 about.tsxprofile.tsx

  • pages 目录下创建 aboutprofile 文件夹;再在两个文件夹中分别创建 index.tsx

❗需要注意的是区分大小写

Scenario 3 Nested Routes

嵌套路由也就是文件夹的嵌套,实现方式还是两种,同上

pages 目录下先创建 blog 目录

firstsecond 可以是文件夹其中包含 index.tsx 文件;也可以是 first.tsxsecond.tsx

Scenario 4 Dynamic Routes

存在 product 列表页和 Product 详情页,地址栏中的 id 是会发生变化的,是动态的

首先实现 product 列表页很简单,在 pages 目录下创建 product 目录 → index.tsx 文件

重点:动态 id 只需要将文件名用中括号包裹起来即可,如 [productId].tsx 。在 product 目录下创建 [productId].tsx 文件,然后在地址栏中输入 http://localhost:3000/product/1 ,就会出现 [productId].tsx 组件中的内容。

组价内容根据 productId 动态展示的话可以通过 useRouter 获取路由信息

import React from "react";
import { useRouter } from "next/router";

export default function ProductDetail() {
  const { query } = useRouter();
  const productId = query.productId;
  return (
    <>
      <h1>ProductDetail {productId} Page</h1>
    </>
  );
}

额外:如果在 product 目录下存在了 sweater.tsx 文件,地址栏输入的是http://localhost:3000/product/sweater,那么展示的内容是哪个组件里的呢,答案是sweater.tsx

Scenario 5 Nested Dynamic Routes

这个场景就是 productId 是动态的,并且 reviewId 也是动态的

  • product 目录下创建 [productId] 目录

  • [productId] 目录下创建 review 目录

  • review 目录下创建动态的 reviewId 文件

// index.tsx 就是上一个场景中的 [productId].tsx的内容

// [reviewId].tsx
import React from "react";
import { useRouter } from "next/router";

export default function ReviewDetail() {
  const { query } = useRouter();
  const { productId, reviewId } = query;
  return (
    <>
      <h1>
        Review {reviewId} for product {productId}
      </h1>
    </>
  );
}

Scenario 6 Catch all routes

如图有这样的文档页面,比如有文档中有20个特性,每个特性又有20个概念,那么就会有400个路由,这种该怎么实现呢。

如果要获取地址栏 docs 后面的内容,不论后面的内容嵌套了多少层,只需要创建 […params].tsx即可。此时通过 useRouter 获取参数时会返回一个对象,对象的值是数组。而非之前单个的字符串了。

import React from "react";
import { useRouter } from "next/router";

export default function DocsDetail() {
  const { query } = useRouter();
  const { params } = query;
  return (
    <>
      {params &&
        Array.isArray(params) &&
        params.map((item) => {
          return <h1 key={item}>{item}</h1>;
        })}
      <h1>DocsDetail Page</h1>
    </>
  );
}

此时如果地址栏是http://localhost:3000/docs时,由于没有在 docs 目录下创建 index.tsx 文件,页面会报 404。修改这个问题有两种方法:

  1. 添加 index.tsx 文件

  2. […params].tsx 修改为 [[…params]].tsx 即可

Navigation

路由有了,就需要在路由之间的跳转。那么跳转的方式有两种

  1. 使用 Link 组件

  2. 使用 useRouter

使用 NextJS 提供的 Link 组件,可以很方便的跳转

import Link from "next/link";

<Link href="/blog">Blog Page</Link>

Link 组件中传入 href 属性,值为对应的路由地址

注意:在新版本中不要在 Link 组件中添加 a 标签,具体查看官方文档

Link 中还可以传 replace 属性 ,replace 会替换当前浏览器的历史状态而不是再添加一个新的 url

Navigating Programmatically

如图我们需要点击 PlaceOrder 按钮,跳转到 product 页面

这种情况下就需要用到 useRouter ,而不是 Link 组件了

import Link from "next/link";
import { useRouter } from "next/router";

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

  const handleGoProduct = () => {
    router.push("/product");
  };

  return (
    <>
      <div>
        <button onClick={handleGoProduct}>Place Order</button>
      </div>
    </>
  );
}

同时 router 也有 replace 方法,效果与 Link 中的 replace 相同

Custom 404 Page

路由总会有不匹配的时候,NextJS 给我们提供一个 404 页面,但是如果我们想自定义 404 页面时,只需要在 pages 目录下创建一个 404.tsx 组件进行修改即可。

第一部分就先介绍这些

内容及图片均来自 Youtube CodeVolution

 
Share this