這是一份快速參考備忘單,包含 Next.js 的 API 參考列表和一些示例
npx create-next-app@latest
# or
yarn create next-app
# or
pnpm create next-app
或者創(chuàng)建 TypeScript 項目
npx create-next-app@latest --typescript
# or
yarn create next-app --typescript
# or
pnpm create next-app --typescript
運行 npm run dev 或 yarn dev 或 pnpm dev 以在 http://localhost:3000 上啟動開發(fā)服務器
使用以下內容填充 pages/index.js:
function HomePage() {
return <div>Welcome to Next.js!</div>
}
export default HomePage
Next.js 是圍繞頁面的概念構建的。 頁面是從 pages 目錄中的 .js、.jsx、.ts 或 .tsx 文件導出的 React 組件
function Page({ data }) {
// 渲染數(shù)據(jù)...
}
// 每個請求都會調用它
export async function getServerSideProps() {
// 從外部 API 獲取數(shù)據(jù)
const res = await fetch(`https://.../data`)
const data = await res.json()
// 通過 props 向頁面?zhèn)鬟f數(shù)據(jù)
return { props: { data } }
}
export default Page
如果您從頁面導出一個名為 getServerSideProps(服務器端渲染)的函數(shù),Next.js 將使用 getServerSideProps 返回的數(shù)據(jù)在每個請求上預渲染該頁面
getServerSideProps 在請求時運行,此頁面將使用返回的 props 進行預渲染next/link 或 next/router 在客戶端頁面轉換上請求此頁面時,Next.js 會向服務器發(fā)送 API 請求,服務器運行 getServerSideProps// pages/posts/[id].js
export async function getStaticPaths() {
// 當這是真的時(在預覽環(huán)境中)不要預呈現(xiàn)任何靜態(tài)頁面(更快的構建,但更慢的初始頁面加載)
if (process.env.SKIP_BUILD_STATIC_GENERATION) {
return {
paths: [],
fallback: 'blocking',
}
}
// 調用外部 API 端點以獲取帖子
const res = await fetch('https://.../posts')
const posts = await res.json()
// 根據(jù)帖子獲取我們要預渲染的路徑 在生產(chǎn)環(huán)境中,預渲染所有頁面
// (構建速度較慢,但初始頁面加載速度較快)
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// { fallback: false } 表示其他路由應該 404
return { paths, fallback: false }
}
如果頁面具有動態(tài)路由并使用 getStaticProps,則需要定義要靜態(tài)生成的路徑列表
getStaticProps 生成 HTML 和 JSON 文件,這兩種文件都可以由 CDN 緩存以提高性能// 帖子將在構建時由 getStaticProps() 填充
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// 這個函數(shù)在服務器端的構建時被調用。
// 它不會在客戶端調用,因此您甚至可以直接進行數(shù)據(jù)庫查詢。
export async function getStaticProps() {
// 調用外部 API 端點以獲取帖子。 您可以使用任何數(shù)據(jù)獲取庫
const res = await fetch('https://.../posts')
const posts = await res.json()
// 通過返回 { props: { posts } },Blog 組件將在構建時接收 `posts` 作為 prop
return {
props: {
posts,
},
}
}
export default Blog
在服務器端的構建時被調用
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
// 這個函數(shù)在服務器端的構建時被調用
// 如果啟用了重新驗證并且有新請求進入,它可能會在無服務器功能上再次調用
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js 將嘗試重新生成頁面:
// - 當請求進來時
// - 最多每 10 秒一次
revalidate: 10, // 片刻之間
}
}
// 這個函數(shù)在服務器端的構建時被調用
// 如果尚未生成路徑,則可能會在無服務器函數(shù)上再次調用它
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json()
// 根據(jù)帖子獲取我們要預渲染的路徑
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// 我們將在構建時僅預渲染這些路徑
// { fallback: blocking } 如果路徑不存在,服務器將按需呈現(xiàn)頁面
return { paths, fallback: 'blocking' }
}
export default Blog
import { useState, useEffect } from 'react'
function Profile() {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetch('/api/profile-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, [])
if (isLoading) return <p>Loading...</p>
if (!data) return <p>No profile data</p>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
import useSWR from 'swr'
const fetcher = (...args) => fetch(...args).then((res) => res.json())
function Profile() {
const { data, error } = useSWR('/api/profile-data', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
Next.js 可以在根目錄中名為 public 的文件夾下提供靜態(tài)文件,如圖像。 然后,您的代碼可以從基本 URL (/) 開始引用 public 中的文件
import Image from 'next/image'
function Avatar() {
return (
<Image
src="/me.png"
alt="me"
width="64"
height="64"
/>
)
}
export default Avatar
Next.js 支持零配置的現(xiàn)代瀏覽器
Next.js 支持在 package.json 文件中配置 Browserslist
{
"browserslist": [
"chrome 64",
"edge 79",
"firefox 67",
"opera 51",
"safari 12"
]
}
如果不存在,請創(chuàng)建一個 pages/_app.js 文件。 然后,導入 styles.css 文件
import '../styles.css';
// 在新的“pages/_app.js”文件中需要此默認導出
export default function MyApp({
Component, pageProps
}) {
return <Component {...pageProps} />
}
例如,考慮以下名為 styles.css 的樣式表
body {
font-family:
'SF Pro Text', 'SF Pro Icons',
'Helvetica Neue', 'Helvetica',
'Arial', sans-serif;
margin: 0 auto;
}
對于全局樣式表,如 bootstrap 或 nprogress,您應該在 pages/_app.js 中導入文件
// pages/_app.js
import 'bootstrap/dist/css/bootstrap.css'
export default function MyApp({
Component, pageProps
}) {
return <Component {...pageProps} />
}
從 node_modules 導入 CSS 文件
您無需擔心 .error {} 與任何其他 .css 或 .module.css 文件!他將被生成 hash 名稱
.error {
color: white;
background-color: red;
}
然后,創(chuàng)建 components/Button.js,導入并使用上面的 CSS 文件:
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
// 請注意“error”類
// 是如何作為導入的“styles”對象的屬性訪問的
className={styles.error}
>
Destroy
</button>
)
}
Next.js 允許您使用 .scss 和 .sass 擴展名導入 Sass,可以通過 CSS 模塊和 .module.scss 或 .module.sass 擴展名使用組件級 Sass
$ npm install --save-dev sass
在使用 Next.js 的內置 Sass 支持之前,請務必sass
通過在 next.config.js 中使用 sassOptions 來實現(xiàn)配置 Sass 編譯器。例如添加 includePaths:
const path = require('path')
module.exports = {
sassOptions: {
includePaths:
[path.join(__dirname, 'styles')],
},
}
/* variables.module.scss */
$primary-color: #64ff00;
:export {
primaryColor: $primary-color;
}
在 pages/_app.js 中導入 variables.module.scss
import variables from '../styles/variables.module.scss'
export default function MyApp({ Component, pageProps }) {
return (
<Layout color={variables.primaryColor}>
<Component {...pageProps} />
</Layout>
)
}
最簡單的一種是內聯(lián)樣式:
function HiThere() {
return (
<p style={{ color: 'red' }}>hi 這里</p>
)
}
export default HiThere
使用 styled-jsx 的組件如下所示:
function HelloWorld() {
return (
<div>
Hello world
<p>scoped!</p>
<style jsx>{`
p { color: blue; }
div { background: red; }
@media (max-width: 600px) {
div { background: blue; }
}
`}</style>
<style global jsx>{`
body { background: black; }
`}</style>
</div>
)
}
export default HelloWorld
當然,你也可以使用 styled-components
// components/layout.js
import Navbar from './navbar'
import Footer from './footer'
export default function Layout({ children }) {
return (
<>
<Navbar />
<main>{children}</main>
<Footer />
</>
)
}
// pages/_app.js
import Layout from '../components/layout'
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
// pages/index.tsx
import type { ReactElement } from 'react'
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
import type { NextPageWithLayout } from './_app'
const Page: NextPageWithLayout = () => {
return <p>hello world</p>
}
Page.getLayout = function getLayout(page: ReactElement) {
return (
<Layout>
<NestedLayout>{page}</NestedLayout>
</Layout>
)
}
export default Page
// pages/_app.tsx
import type { ReactElement, ReactNode } from 'react'
import type { NextPage } from 'next'
import type { AppProps } from 'next/app'
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode
}
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout
}
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
// 使用在頁面級別定義的布局(如果可用)
const getLayout = Component.getLayout ?? ((page) => page)
return getLayout(<Component {...pageProps} />)
}
// pages/index.js
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
export default function Page() {
return (
/** Your content */
)
}
Page.getLayout = function getLayout(page) {
return (
<Layout>
<NestedLayout>{page}</NestedLayout>
</Layout>
)
}
// pages/_app.js
export default function MyApp({ Component, pageProps }) {
// 使用在頁面級別定義的布局(如果可用)
const getLayout = Component.getLayout || ((page) => page)
return getLayout(<Component {...pageProps} />)
}
// components/layout.js
import useSWR from 'swr'
import Navbar from './navbar'
import Footer from './footer'
export default function Layout({ children }) {
const { data, error } = useSWR('/api/navigation', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
return (
<>
<Navbar links={data.links} />
<main>{children}</main>
<Footer />
</>
)
}
import Image from 'next/image'
import profilePic from '../public/me.png'
function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src={profilePic}
alt="Picture of the author"
// width={500} 自動提供
// height={500} 自動提供
// blurDataURL="data:..." 自動提供
// placeholder="blur" // 加載時可選的模糊處理
/>
<p>Welcome to my homepage!</p>
</>
)
}
import Image from 'next/image'
export default function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src="/me.png"
alt="Picture of the author"
width={500}
height={500}
/>
<p>Welcome to my homepage!</p>
</>
)
}
要使用遠程圖像,src 屬性應該是一個 URL 字符串,可以是相對的也可以是絕對的
您應該將優(yōu)先級屬性添加到將成為每個頁面的 Largest Contentful Paint (LCP) 元素的圖像。 這樣做允許 Next.js 專門確定要加載的圖像的優(yōu)先級(例如,通過預加載標簽或優(yōu)先級提示),從而顯著提高 LCP
import Image from 'next/image'
export default function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src="/me.png"
alt="Picture of the author"
width={500}
height={500}
priority
/>
<p>Welcome to my homepage!</p>
</>
)
}
自動托管任何 Google 字體。 字體包含在部署中,并從與您的部署相同的域提供服務。 瀏覽器不會向 Google 發(fā)送任何請求
// pages/_app.js
import { Inter } from '@next/font/google'
// 如果加載可變字體,則無需指定字體粗細
const inter = Inter({ subsets: ['latin'] })
export default function MyApp({
Component, pageProps
}) {
return (
<main className={inter.className}>
<Component {...pageProps} />
</main>
)
}
如果不能使用可變字體,則需要指定粗細:
// pages/_app.js
import { Roboto } from '@next/font/google'
const roboto = Roboto({
weight: '400',
subsets: ['latin'],
})
export default function MyApp({
Component, pageProps
}) {
return (
<main className={roboto.className}>
<Component {...pageProps} />
</main>
)
}
const roboto = Roboto({
weight: ['400', '700'],
style: ['normal', 'italic'],
subsets: ['latin'],
})
// pages/_app.js
import { Inter } from '@next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function MyApp({ Component, pageProps }) {
return (
<>
<style jsx global>{`
html {
font-family: ${inter.style.fontFamily};
}
`}</style>
<Component {...pageProps} />
</>
)
}
// pages/index.js
import { Inter } from '@next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function Home() {
return (
<div className={inter.className}>
<p>Hello World</p>
</div>
)
}
// pages/_app.js
const inter = Inter({ subsets: ['latin'] })
在 next.config.js 中全局使用所有字體
// next.config.js
module.exports = {
experimental: {
fontLoaders: [
{
loader: '@next/font/google',
options: { subsets: ['latin'] }
},
],
},
}
如果兩者都配置,則使用函數(shù)調用中的子集
// pages/_app.js
import localFont from '@next/font/local'
// 字體文件可以位于“pages”內
const myFont = localFont({
src: './my-font.woff2'
})
export default function MyApp({
Component, pageProps
}) {
return (
<main className={myFont.className}>
<Component {...pageProps} />
</main>
)
}
如果要為單個字體系列使用多個文件,src 可以是一個數(shù)組:
const roboto = localFont({
src: [
{
path: './Roboto-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './Roboto-Italic.woff2',
weight: '400',
style: 'italic',
},
{
path: './Roboto-Bold.woff2',
weight: '700',
style: 'normal',
},
{
path: './Roboto-BoldItalic.woff2',
weight: '700',
style: 'italic',
},
],
})
// pages/_app.js
import { Inter } from '@next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
});
export default function MyApp({ Component, pageProps }) {
return (
<main className={`${inter.variable} font-sans`}>
<Component {...pageProps} />
</main>
)
}
最后,將 CSS 變量添加到您的 Tailwind CSS 配置中:
// tailwind.config.js
const { fontFamily } = require('tailwindcss/defaultTheme')
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
fontFamily: {
sans: ['var(--font-inter)', ...fontFamily.sans],
},
},
},
plugins: [],
}
import Script from 'next/script'
export default function Dashboard() {
return (
<>
<Script
src="https://example.com/script.js"
/>
</>
)
}
要為所有路由加載第三方腳本,導入 next/script 并將腳本直接包含在 pages/_app.js 中
import Script from 'next/script'
export default function MyApp({
Component, pageProps
}) {
return (
<>
<Script
src="https://example.com/script.js"
/>
<Component {...pageProps} />
</>
)
}
此策略仍處于試驗階段,只有在 next.config.js 中啟用了 nextScriptWorkers 標志時才能使用:
module.exports = {
experimental: {
nextScriptWorkers: true,
},
}
設置完成后,定義 strategy="worker" 將自動在您的應用程序中實例化 Partytown 并將腳本卸載到網(wǎng)絡工作者
import Script from 'next/script'
export default function Home() {
return (
<>
<Script
src="https://example.com/script.js"
strategy="worker"
/>
</>
)
}
import Script from 'next/script'
export default function Page() {
return (
<>
<Script
src="https://example.com/script.js"
id="example-script"
nonce="XUENAJFW"
data-test="script"
/>
</>
)
}
<Script id="show-banner">
{`document.getElementById('banner').classList.remove('hidden')`}
</Script>
<Script
id="show-banner"
dangerouslySetInnerHTML={{
__html: `document.getElementById('banner').classList.remove('hidden')`,
}}
/>
import Script from 'next/script'
export default function Page() {
return (
<>
<Script
src="https://example.com/script.js"
onLoad={() => {
console.log('Script has loaded')
}}
/>
</>
)
}
"scripts": {
"lint": "next lint"
}
然后運行 npm run lint 或 yarn lint:
yarn lint
# 你會看到這樣的提示:
#
# ? 您想如何配置 ESLint?
#
# ? 基本配置 + Core Web Vitals 規(guī)則集(推薦)
# 基本配置
# None
Strict 嚴格配置:包括 Next.js 的基本 ESLint 配置以及更嚴格的 Core Web Vitals 規(guī)則集
{
"extends": "next/core-web-vitals"
}
Base 基礎配置:包括 Next.js 的基本 ESLint 配置
{
"extends": "next"
}
項目的根目錄中創(chuàng)建一個包含所選配置的 .eslintrc.json 文件
{
"extends": "next",
"settings": {
"next": {
"rootDir": "packages/my-app/"
}
}
}
rootDir 可以是路徑(相對或絕對)、glob(即“packages/*/”)或路徑和/或 glob 數(shù)組
module.exports = {
eslint: {
dirs: ['pages', 'utils'],
},
}
在生產(chǎn)構建期間(next build)僅在“pages”和“utils”目錄上運行 ESLint,或者使用命令
$ next lint --dir pages --dir utils --file bar.js
您可以使用 .eslintrc 中的 rules 屬性直接更改它們:
{
"extends": "next",
"rules": {
"react/no-unescaped-entities": "off",
"@next/next/no-page-custom-font": "off"
}
}
修改或禁用受支持的插件(react、react-hooks、next)提供的任何規(guī)則
{
"extends": "next/core-web-vitals"
}
npm install -S eslint-config-prettier
# or
yarn add --dev eslint-config-prettier
{
"extends": ["next", "prettier"]
}
const path = require('path')
const buildEslintCommand = (filenames) =>
`next lint --fix --file ${filenames
.map((f) => path.relative(process.cwd(), f))
.join(' --file ')}`;
module.exports = {
'*.{js,jsx,ts,tsx}': [buildEslintCommand],
}
內容添加到項目根目錄中的 .lintstagedrc.js 文件中,以指定 --file 標志
npx create-next-app@latest --ts
# or
yarn create next-app --typescript
# or
pnpm create next-app --ts
import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'
export const getStaticProps: GetStaticProps = async (context) => {
// ...
}
export const getStaticPaths: GetStaticPaths = async () => {
// ...
}
export const getServerSideProps: GetServerSideProps = async (context) => {
// ...
}
touch tsconfig.json
您還可以通過在 next.config.js 文件中設置 typescript.tsconfigPath 屬性來提供 tsconfig.json 文件的相對路徑
import type {
NextApiRequest, NextApiResponse
} from 'next'
export default (
req: NextApiRequest,
res: NextApiResponse
) => {
res.status(200).json({ name:'John Doe' })
}
您還可以鍵入響應數(shù)據(jù):
import type {
NextApiRequest, NextApiResponse
} from 'next'
type Data = {
name: string
}
export default (
req: NextApiRequest,
res: NextApiResponse<Data>
) => {
res.status(200).json({ name:'John Doe' })
}
使用內置類型 AppProps 并將文件名更改為 ./pages/_app.tsx,如下所示:
import type { AppProps } from 'next/app'
export default function MyApp({
Component, pageProps
}: AppProps) {
return <Component {...pageProps} />
}
// @ts-check
/**
* @type {import('next').NextConfig}
**/
const nextConfig = {
/* 配置選項在這里 */
}
module.exports = nextConfig
module.exports = {
typescript: {
ignoreBuildErrors: true,
},
}
危險地允許生產(chǎn)構建成功完成,即使您的項目有類型錯誤
將環(huán)境變量從 .env.local 加載到 process.env 中
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword
使用環(huán)境變量
// pages/index.js
export async function getStaticProps() {
const db = await myDB.connect({
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS,
})
// ...
}
# .env
HOSTNAME=localhost
PORT=8080
HOST=http://$HOSTNAME:$PORT
如果您嘗試使用實際值中帶有 $ 的變量,則需要像這樣對其進行轉義:\$
# .env
A=abc
# becomes "preabc"
WRONG=pre$A
# becomes "pre$A"
CORRECT=pre\$A
為了向瀏覽器公開變量,您必須在變量前加上 NEXT_PUBLIC_ 前綴
NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk
NEXT_PUBLIC_ANALYTICS_ID 可以在此處使用,因為它的前綴是 NEXT_PUBLIC_
// pages/index.js
import setupAnalyticsService from '../lib/my-analytics-service'
//
// 它將在構建時轉換為 `setupAnalyticsService('abcdefghijk')`
setupAnalyticsService(process.env.NEXT_PUBLIC_ANALYTICS_ID)
function HomePage() {
return <h1>Hello World</h1>
}
export default HomePage
路由器將自動將名為 index 的文件路由到目錄的根目錄
| :-- | -- |
|---|---|
pages/index.js | / |
pages/blog/index.js | /blog |
路由器支持嵌套文件。如果創(chuàng)建嵌套文件夾結構,文件將以同樣的方式自動路由
| :-- | -- |
|---|---|
pages/blog/first-post.js | /blog/first-post |
pages/dashboard/settings/username.js | /dashboard/settings/username |
動態(tài)路由
| :-- | -- |
|---|---|
pages/blog/[slug].js | /blog/:slug/blog/hello-world |
pages/[username]/settings.js | /:username/settings/foo/settings |
pages/post/[...all].js | /post/*/post/2020/id/title |
如果您創(chuàng)建一個名為 pages/posts/[pid].js 的文件,那么它可以在 posts/1、posts/2 等處訪問
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { pid } = router.query
return <p>Post: {pid}</p>
}
export default Post
使用 useRouter 獲取動態(tài)路由參數(shù) pid
import Link from 'next/link'
export default function Home() {
return (
<ul>
<li>
<Link href="/">首頁</Link>
</li>
<li>
<Link href="/about">關于我們</Link>
</li>
<li>
<Link href="/blog/hello-world">
博文
</Link>
</li>
</ul>
)
}
| :-- | -- |
|---|---|
/ | pages/index.js |
/about | pages/about.js |
/blog/hello-world | pages/blog/[slug].js |
import Link from 'next/link'
export default function Posts({ posts }) {
return (
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
標題
</Link>
)
}
import Link from 'next/link'
export default function Posts({ posts }) {
return (
<Link
href={{
pathname: '/blog/[slug]',
query: { slug: posts.slug },
}}
>
標題
</Link>
)
}
考慮以下頁面 pages/post/[pid].js:
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { pid } = router.query
return <p>Post: {pid}</p>
}
export default Post
到動態(tài)路由的客戶端導航由 next/link 處理
import Link from 'next/link'
export default function Home() {
return (
<div>
<Link href="/post/abc">
轉到 pages/post/[pid].js
</Link>
<Link href="/post/abc?foo=bar">
也轉到 pages/post/[pid].js
</Link>
<Link href="/post/abc/a-comment">
轉到 pages/post/[pid]/[comment].js
</Link>
</div>
)
}
工作方式相同。 頁面 pages/post/[pid]/[comment].js 將匹配路由 /post/abc/a-comment 并且它的查詢對象將是:
{ "pid": "abc", "comment": "a-comment" }
可以通過在括號內添加三個點 (...) 來擴展動態(tài)路由以捕獲所有路徑,pages/post/[...slug].js 匹配 /post/a,也匹配 /post/a/b、/post/a/b/c 等
// /post/a
{ "slug": ["a"] }
// /post/a/b
{ "slug": ["a", "b"] }
使用 [[...slug]],pages/post/[[...slug]].js 將匹配 /post、/post/a、/post/a/b 等
// GET `/post` (empty object)
{ }
// `GET /post/a` (single-element array)
{ "slug": ["a"] }
// `GET /post/a/b` (multi-element array)
{ "slug": ["a", "b"] }
import { useRouter } from 'next/router'
export default function ReadMore() {
const router = useRouter()
return (
<button
onClick={() => router.push('/about')}
>
點擊這里閱讀更多
</button>
)
}
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// 當前網(wǎng)址為“/”
export default function Page() {
const router = useRouter()
useEffect(() => {
// 始終在第一次渲染后進行導航
router.push('/?counter=10', undefined, { shallow: true })
}, [])
useEffect(() => {
// counter 變了!
}, [router.query.counter])
}
淺路由僅適用于當前頁面中的 URL 更改。 例如,假設我們有另一個名為 pages/about.js 的頁面,并且您運行以下命令:
router.push('/?counter=10', '/about?counter=10', { shallow: true })
由于這是一個新頁面,它會卸載當前頁面,加載新頁面并等待數(shù)據(jù)獲取,即使我們要求進行淺層路由
感谢您访问我们的网站,您可能还对以下资源感兴趣:
国产成人精品999视频&日本一区二区亚洲人妻精品&久久久精品国产99久久精&99热这里只有成人精品国产&精品国产剧情av一区二区&成人亚洲精品久久久久app&国产精品美女高潮抽搐A片