路由切换时仅重载右侧内容的侧边栏客户端渲染问题
解决路由切换仅重载右侧内容的方案
问题根源
页面全重载主要是两个原因:
- 布局没作为持久化的根布局,路由切换时整个布局跟着重新渲染
- Navbar组件不是客户端组件,
router.push没法触发客户端路由,只能走全页面跳转
修复步骤
1. 把布局设为持久化根布局
如果用的是Next.js App Router,把布局放在app/layout.tsx(根布局)里,这样布局会一直挂载,只有{children}部分随路由更新:
// app/layout.tsx import { MantineProvider } from '@mantine/core'; import { AppShell } from '@mantine/core'; import HomeNavbar from './components/HomeNavbar'; import theme from './theme'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <MantineProvider defaultColorScheme="dark" theme={theme}> <AppShell navbar={{ width: 250, breakpoint: 0 }} padding={{ base: 10, sm: 15, lg: 'xl' }}> <HomeNavbar /> {children} </AppShell> </MantineProvider> </body> </html> ); }
2. 给Navbar加上客户端组件标识
在HomeNavbar顶部加'use client',因为客户端路由相关的操作必须在客户端组件里执行:
// components/HomeNavbar.tsx 'use client'; // 这行必须加 import { AppShell, Image, Title, ColorSchemeToggle } from '@mantine/core'; import { useRouter } from 'next/navigation'; import classes from './HomeNavbar.module.css'; export default function HomeNavbar() { const router = useRouter(); const data = [/* 你的链接数据 */]; const activeLink = ''; // 你的激活状态逻辑 return ( <AppShell.Navbar> <nav className={classes.navbar}> <div className={classes.wrapper}> <div className={classes.aside}> <div className={classes.logo}> <Image src={'/logo.jpeg'} alt="Ben" width="40" height="40" /> </div> {/* {mainLinks} */} </div> <div className={classes.main}> <Title order={4} className={classes.title}></Title> {data.map((link) => ( <a className={classes.link} data-active={activeLink === link.label || undefined} key={link.label} onClick={(e) => { e.preventDefault(); router.push(link.link); }} > {link.label} </a> ))} </div> </div> <div className={classes.footer}> <ColorSchemeToggle /> </div> </nav> </AppShell.Navbar> ); }
3. 改用Next.js Link组件(更省心)
手动写a标签加点击事件容易出错,直接用Next.js的Link组件,它自带客户端路由功能,不用额外处理:
// 先导入Link import Link from 'next/link'; // 替换原来的a标签: {data.map((link) => ( <Link href={link.link} className={classes.link} data-active={activeLink === link.label || undefined} key={link.label} > {link.label} </Link> ))}
这样切换路由时只会更新右侧的{children},Navbar保持不动,也不会全页面重载。
验证方法
- 打开浏览器开发者工具的「网络」面板,切换路由时只会加载页面相关资源,不会刷新整个文档
- 检查Navbar是否在路由切换时没有重新渲染(可以加个
console.log验证)
内容的提问来源于stack exchange,提问作者user1688346
相关产品推荐
相关产品推荐

