搭建项目,实现了基础框架和头部导航,记录其中涉及的路由定义、路由状态与跳转、布局、特殊页面、Metadata 文件等知识点。公共布局、导航、404页面等代码使用 Ant Design 作为示例。
路由定义
路由入口文件
路由入口文件,page.tsx
,里面就是这个路由默认渲染的内容。有点类似于 index.html
的效果。
特殊文件约定
https://nextjs.org/docs/app/api-reference/file-conventions
- default.js 在整页加载后无法恢复时呈现回退
- error.js 发生意外错误时显示,常用
- instrumentation.js 监视和日志记录工具
- layout.js 公共布局文件,常用
- loading.js 基于 Suspense 构建的加载状态,常用
- middleware.js 中间件,常用
- not-found.js 404 页面,常用
- page.js 路由默认入口文件,常用
- route.js 创建各种 HTTP 方法的自定义请求处理,常用
- template.js 模板
纯组件目录
在 app 目录中, 以 _
下划线开头的目录不会作为路由页面使用,可用于放组件。
路由组
https://nextjs.org/docs/app/building-your-application/routing/colocation#route-groups
可以通过将文件夹括在括号中来创建路由组: (folderName) ,这表示该文件夹用于组织目的,不应包含在路由的 URL 路径中。如:
(test)/page.tsx
页面,访问路径为/
(test)/something/page.tsx
页面,访问路径为/something
动态路由
https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes
动态路由,可通过目录路径中的 [id]
表示参数。
获取参数:
const IdPage = ({params}: {params: {id:string}}) => {
return <div>ID page: {params.id}</div>
}
[...slug]
路径表示将 url 后面的每一段都读取,作为数组[[...slug]]
表示后续的路由段可为空
路由状态与跳转
usePathname 获取当前路由
通过 usePathname
可获取当前路径,用于判断导航当前激活状态。
import { usePathname } from 'next/navigation';
const items = [
{
key: '/',
label: '首页',
},
{
key: '/about',
label: '关于',
}
]
const Nav = () => {
const pathName = usePathname();
return <Menu
theme="light"
mode="horizontal"
defaultSelectedKeys={[pathName]}
items={items}
style={{
flex: 1,
minWidth: 0,
borderBottom: 'unset',
justifyContent: 'flex-end'
}}
/>
}
Link 路由跳转
<Link href="/" style={{
width: '153px',
height: '38px',
marginRight: '20px'
}}>
<Image src="/logo.svg" width={153} height={38} alt="logo" />
</Link>
默认启用预加载,可设置 prefetch 为 false 来禁止。
<Link href="/" prefetch={false}></Link>
useRouter 跳转
import { useRouter } from 'next/navigation';
const router = useRouter();
const onClick: MenuProps['onClick'] = e => {
router.push(e.key);
}
useSearchParams 获取请求参数
获取:
const searchParams = useSearchParams();
const v = searchParams.get('v');
在客户端组件使用时需要被 Suspense
组件包裹,可通过 fallback 设置 loading 或骨架屏。
searchParams 没有 set 方法,通过 useRouter 或 Link 改变路由实现改变 searchParams 。
布局与特殊页面
公共布局文件
https://nextjs.org/docs/app/api-reference/file-conventions/layout
layout.tsx 可用于编写公共布局文件,生效于所有子目录的文件。
也可以在这里设置 Ant Design 的全局样式和配置。
使用单独的 CommonLayout 客户端组件去引入 Ant Design 组件。
import { AntdRegistry } from '@ant-design/nextjs-registry';
import { ConfigProvider } from "antd";
import type { Metadata } from "next";
import CommonLayout from "./_components/CommonLayout";
import "./globals.css";
export const metadata: Metadata = {
title: "Next.js Fullstack Demo",
description: "Generated by heibaimeng",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="zh">
<body>
<AntdRegistry>
<ConfigProvider
theme={{
token: {
colorPrimary: '#003366',
},
components: {
Layout: {
headerBg: '#fff'
},
},
}}
>
<CommonLayout>
{children}
</CommonLayout>
</ConfigProvider>
</AntdRegistry>
</body>
</html>
);
}
not-found
https://nextjs.org/docs/app/api-reference/file-conventions/not-found
import Link from "next/link"
import { Button, Result } from 'antd';
const NotFound = () => (
<Result
status="404"
title="404"
subTitle="抱歉,您访问的页面不存在。"
extra={<Link href="/"><Button type="primary">回到首页</Button></Link>}
/>
);
export default NotFound;
error
https://nextjs.org/docs/app/api-reference/file-conventions/error
在服务端组件中抛出 Error ,可看到效果。
"use client"
import Link from "next/link"
import { Button, Result } from 'antd';
const Error = () => (
<Result
status="500"
title="500"
subTitle="抱歉,页面出现错误。"
extra={<Link href="/"><Button type="primary">回到首页</Button></Link>}
/>
);
export default Error;
loading
https://nextjs.org/docs/app/api-reference/file-conventions/loading
打开控制台切换到 slow 3g ,再切换路由,可看到效果。
import { Spin } from 'antd';
const Loading = () => {
return (
<div style={{
width: '100%',
height: '150px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<Spin size="large" />
</div>
)
}
export default Loading
Metadata 文件
配置 metadate
https://nextjs.org/docs/app/building-your-application/optimizing/metadata
可以直接 export 一个对象来设置,配置标题、描述、网站 icon,比以前方便不少。
export const metadata: Metadata = {
title: "Next.js Fullstack Demo",
description: "Generated by heibaimeng",
};
可在公共布局文件中设置公共的 metadata ,并可以在页面路由组件内单独设置来覆盖它。
sitemap
https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap
在 app 目录下创建 sitemap.ts
可动态创建 sitemap.xml
文件。如:
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://heibaimeng.com',
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
},
{
url: 'https://heibaimeng.com/collections/1',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
]
}
其他文件
- favicon, icon, and apple-icon 图标设置
- manifest.json PWA 的 Web 应用程序清单
- opengraph-image and twitter-image Open Graph 和 Twitter 图像
- robots.txt 告知搜索引擎允许抓取哪些页面