如何在Next.js中实现带持久侧边栏的Admin路由父组件
我懂你在React Router里的那种实现思路,换到Next.js的文件路由体系下,确实得调整下方式,下面分两种主流的Next.js路由方案,给你讲讲怎么实现Admin子页面共享Sidebar且切换路由时不重渲染:
Pages Router(Next.js 12及更早,或仍使用pages目录的项目)
方式1:手动引入布局组件(更直观)
- 先创建复用的Admin布局组件
在项目的components文件夹下新建AdminLayout.js,把Sidebar和通用布局逻辑放这里:
import Link from 'next/link'; const Sidebar = () => ( <div style={{ width: '200px', borderRight: '1px solid #eee' }}> <h2>Frontend</h2> <p><Link href="/admin">Admin</Link></p> <p><Link href="/admin/customize">Customize</Link></p> <p><Link href="/admin/settings">Settings</Link></p> <p><Link href="/admin/account">Account</Link></p> </div> ); const AdminLayout = ({ children }) => { return ( <div style={{ display: 'flex' }}> <Sidebar /> <div style={{ flex: 1, padding: '20px' }}> {children} {/* 这里会渲染各个子页面的内容 */} </div> <footer style={{ position: 'fixed', bottom: 0, width: '100%', borderTop: '1px solid #eee', padding: '10px' }}> Bottom </footer> </div> ); }; export default AdminLayout;
- 搭建Admin子页面的文件结构
在pages目录下创建admin文件夹,然后逐个添加子页面文件:
pages/admin/index.js(Admin首页)pages/admin/customize.jspages/admin/settings.jspages/admin/account.js
- 在子页面中使用布局
比如pages/admin/customize.js,只需要把页面内容嵌套进AdminLayout即可:
import AdminLayout from '../../components/AdminLayout'; const Customize = () => { return ( <AdminLayout> <h1>Customize</h1> </AdminLayout> ); }; export default Customize;
这种方式下,切换Admin下的子路由时,Sidebar属于布局组件的一部分,只会渲染一次,不会随着子页面切换重新挂载。
方式2:全局自动匹配路由(更省心)
如果你不想每个Admin子页面都手动导入布局,可以在pages/_app.js里做路由判断,自动给Admin路径的页面套上布局:
import '../styles/globals.css'; import AdminLayout from '../components/AdminLayout'; function MyApp({ Component, pageProps, router }) { // 判断当前路由是否属于Admin路径 if (router.pathname.startsWith('/admin')) { return ( <AdminLayout> <Component {...pageProps} /> </AdminLayout> ); } return <Component {...pageProps} />; } export default MyApp;
这样所有/admin开头的页面都会自动应用Admin布局,无需手动引入。
App Router(Next.js 13+,使用app目录)
App Router原生支持持久化布局,实现起来更简洁,完全贴合你的需求:
- 搭建Admin的目录结构
在app目录下创建admin文件夹,然后按如下结构创建文件:
app/ └── admin/ ├── layout.js # Admin的父布局(自动应用给所有子路由) ├── page.js # Admin首页 ├── customize/ │ └── page.js ├── settings/ │ └── page.js └── account/ └── page.js
- 编写Admin的布局文件
layout.js
import Link from 'next/link'; const Sidebar = () => ( <div style={{ width: '200px', borderRight: '1px solid #eee' }}> <h2>Frontend</h2> <p><Link href="/admin">Admin</Link></p> <p><Link href="/admin/customize">Customize</Link></p> <p><Link href="/admin/settings">Settings</Link></p> <p><Link href="/admin/account">Account</Link></p> </div> ); export default function AdminLayout({ children }) { return ( <div style={{ display: 'flex' }}> <Sidebar /> <div style={{ flex: 1, padding: '20px' }}> {children} </div> <footer style={{ position: 'fixed', bottom: 0, width: '100%', borderTop: '1px solid #eee', padding: '10px' }}> Bottom </footer> </div> ); }
App Router的布局组件默认是持久化的,切换子路由时,layout.js里的Sidebar不会重新渲染,只会更新children对应的子页面内容,完美满足你“Sidebar仅渲染一次”的需求。
- 编写子页面内容
比如app/admin/customize/page.js,只需要写页面核心内容即可,无需手动引入布局:
export default function Customize() { return <h1>Customize</h1>; }
小提示
- Next.js里的跳转组件是
next/link,不要和React Router的Link混淆 - App Router的布局是自动继承的,子路由会自动使用父目录的
layout.js,非常省心 - 如果用Pages Router的全局匹配方式,注意路由判断的准确性,避免误匹配非Admin页面
内容的提问来源于stack exchange,提问作者Velidan
相关产品推荐
相关产品推荐

