React 19 + Next.js 15 中实现混合布局
在 React 19 + Next.js 15 中实现混合布局(全屏/带侧边栏)的推荐方案如下:
方案一:基于文件约定的布局系统(Next.js 15 推荐)
1. 创建布局文件夹结构
app/
├── (fullscreen)/ # 全屏页面组
│ ├── login/
│ │ └── page.js
│ └── landing/
│ └── page.js
├── (with-sidebar)/ # 带侧边栏页面组
│ ├── dashboard/
│ │ └── page.js
│ └── settings/
│ └── page.js
├── layout.js # 根布局
└── template.js # 可复用的模板组件
2. 实现不同布局 (app/(fullscreen)/layout.js
)
// 全屏布局
export default function FullscreenLayout({ children }) {return (<html lang="en" className="h-full"><body className="h-full">{children}</body></html>);
}
3. 带侧边栏布局 (app/(with-sidebar)/layout.js
)
import Sidebar from '@/components/Sidebar';
import Header from '@/components/Header';export default function SidebarLayout({ children }) {return (<div className="flex flex-col min-h-screen"><Header /><div className="flex flex-1"><Sidebar /><main className="flex-1 p-6">{children}</main></div></div>);
}
4. 根布局 (app/layout.js
)
export default function RootLayout({ children }) {return (<html lang="en"><body>{children}</body></html>);
}
方案二:基于条件渲染的布局组件
1. 创建动态布局组件
// components/LayoutSwitcher.js
'use client';import { usePathname } from 'next/navigation';
import SidebarLayout from './SidebarLayout';
import FullscreenLayout from './FullscreenLayout';export default function LayoutSwitcher({ children }) {const pathname = usePathname();const fullscreenPaths = ['/login', '/landing'];return fullscreenPaths.includes(pathname) ? (<FullscreenLayout>{children}</FullscreenLayout>) : (<SidebarLayout>{children}</SidebarLayout>);
}
2. 修改根布局
// app/layout.js
import LayoutSwitcher from '@/components/LayoutSwitcher';export default function RootLayout({ children }) {return (<html lang="en"><body><LayoutSwitcher>{children}</LayoutSwitcher></body></html>);
}
方案三:使用 React 19 的元数据控制
1. 在页面中定义布局类型
// app/dashboard/page.js
export const layout = 'with-sidebar'; // 自定义元数据export default function Dashboard() {return <div>Dashboard Content</div>;
}
2. 创建布局包装器
// app/LayoutWrapper.js
import { getPageLayout } from './getLayout';export default function LayoutWrapper({ children, layoutType }) {const Layout = getPageLayout(layoutType);return <Layout>{children}</Layout>;
}
最佳实践建议
-
CSS 处理:
/* globals.css */ .fullscreen-page {@apply h-screen w-screen overflow-hidden; }.sidebar-layout {@apply flex min-h-screen; }
-
性能优化:
- 使用
React.cache()
记忆化布局组件 - 对侧边栏使用
React.Suspense
延迟加载
- 使用
-
TypeScript 支持:
// types/layout.d.ts type LayoutType = 'fullscreen' | 'with-sidebar';declare module '*.page.js' {export const layout?: LayoutType; }
-
状态共享:
// 使用 React 19 Actions 处理布局状态 const [layout, setLayout] = useActionState((prev, newLayout) => newLayout,'with-sidebar' );
对比总结
方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
文件约定 | 原生支持,清晰隔离 | 需要目录重组 | 新项目 |
条件渲染 | 灵活控制 | 需要客户端渲染 | 已有项目改造 |
元数据 | 声明式配置 | 需要自定义逻辑 | 中型项目 |
选择方案一时,Next.js 15 的路由组功能可以保持URL路径不变((fullscreen)/login
实际访问路径仍是 /login
)