项目概况

NextJS 语法

2026-01-293 min read前端技术
nextjs

我帮你把内容排版和格式优化一下,让你的博客更清晰、易读,同时保留代码示例和说明:


Next.js 中目录就是路由

在 Next.js 13+ 的 App Router 中,目录结构直接对应路由路径,因此命名非常重要。

  • layout.tsx:布局组件,用于包裹页面内容,可以在目录中继承。
  • page.tsx:页面组件,对应具体路由。

目录结构示例

bash
1➜ tree 2└── app 3 ├── blog 4 │ ├── layout.tsx # blog 下的布局 5 │ ├── page.css # blog 页面样式 6 │ ├── page.tsx # /blog 页面 7 │ ├── post 8 │ │ └── page.tsx # /blog/post 页面 9 │ └── posts 10 │ └── [id] 11 │ └── page.tsx # 动态路由 /blog/posts/:id 页面 12 ├── favicon.ico 13 ├── globals.css 14 ├── layout.tsx # 根布局 15 └── page.tsx # 根页面 /

路由对应关系

URL 路径对应文件
/app/page.tsx + app/layout.tsx
/blogapp/blog/page.tsx + app/blog/layout.tsx
/blog/postapp/blog/post/page.tsx + app/blog/layout.tsx
/blog/posts/123app/blog/posts/[id]/page.tsx + app/blog/layout.tsx

💡 小贴士

  • layout.tsx 可以多级嵌套,实现布局复用。
  • [id] 这样的文件夹表示 动态路由,可匹配任意参数。

好的,我帮你加一段 可视化路由树和布局继承关系图,用文本+箭头的方式表示,很适合博客展示:


Next.js 路由树与布局继承示意

text
1app 2├── layout.tsx ← 根布局 3├── page.tsx ← / 根页面 4└── blog 5 ├── layout.tsx ← /blog 专属布局(继承自根布局) 6 ├── page.tsx ← /blog 页面 7 ├── post 8 │ └── page.tsx ← /blog/post 页面(继承 /blog/layout.tsx → 根布局) 9 └── posts 10 └── [id] 11 └── page.tsx ← /blog/posts/:id 页面(继承 /blog/layout.tsx → 根布局)

🔹 继承关系解释

  • 所有页面默认继承最近的上级 layout.tsx,如果没有则继承根布局。

  • /blog/post 的渲染顺序:

    text
    1根布局 app/layout.tsx 23blog 布局 app/blog/layout.tsx 45页面 app/blog/post/page.tsx
  • /blog/posts/123 的渲染顺序:

    text
    1根布局 app/layout.tsx 23blog 布局 app/blog/layout.tsx 45页面 app/blog/posts/[id]/page.tsx

💡 小结:

  • 文件夹结构 = 路由路径
  • layout.tsx = 层级继承布局
  • page.tsx = 页面内容

常用语法

同页面中用css

  • pm add @emotion/css
text
1"use client"; 2import {css} from "@emotion/css"; 3const header = css` 4 width: 100vw; 5 display: flex; 6 flex-direction: row; 7 align-items: center; 8 height: 100%; 9`; 10 11export default function BlogLayout({ 12 children, 13 }: Readonly<{ 14 children: React.ReactNode; 15}>){ 16 17 return (<><div className={header}></div></>) 18}

定义layout

text
1"use client"; 2import {Layout} from '@arco-design/web-react'; 3import "@arco-design/web-react/dist/css/arco.css"; 4import './page.css' 5import React from "react"; 6import {Menu} from '@arco-design/web-react'; 7import {css} from "@emotion/css"; 8 9const MenuItem = Menu.Item; 10const SubMenu = Menu.SubMenu; 11 12 13const Sider = Layout.Sider; 14const Header = Layout.Header; 15const Footer = Layout.Footer; 16const Content = Layout.Content; 17 18const header = css` 19 width: 100vw; 20 display: flex; 21 flex-direction: row; 22 align-items: center; 23 height: 100%; 24`; 25 26export default function BlogLayout({ 27 children, 28 }: Readonly<{ 29 children: React.ReactNode; 30}>) { 31 return (<> 32 <div className='layout-basic-demo'> 33 <Layout className='h-screen'> 34 <Header className='shadow-lg'> 35 <div className={header}> 36 <div className='flex-1'> 37 </div> 38 <div className='flex-2'> 39 <Menu mode='horizontal' defaultSelectedKeys={['1']}> 40 <MenuItem key='1'>Home</MenuItem> 41 <MenuItem key='2'>Solution</MenuItem> 42 <MenuItem key='3'>Cloud Service</MenuItem> 43 <MenuItem key='4'>Cooperation</MenuItem> 44 </Menu> 45 </div> 46 </div> 47 48 </Header> 49 <Content> 50 {children} 51 </Content> 52 <Footer>Footer</Footer> 53 </Layout> 54 </div> 55 </>) 56} 57 58

如何使用动态参数

注意目录要用 [id]

tsx
1"use client"; 2import React from "react"; 3import {useParams} from "next/navigation"; 4 5export default function Post() { 6 const params = useParams(); 7 const id = params?.id; 8 9 if (!id) { 10 return <h1 style={{textAlign: "center", color: "red"}}>未找到</h1>; 11 } 12 13 return <h1 style={{textAlign: "center", color: "black"}}>ID: {id}</h1>; 14} 15