You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 15 App文件夹结构下多导航栏的实现方案及最佳实践咨询

Next.js 15 App文件夹结构下多导航栏的实现方案及最佳实践咨询

Hey there! 刚上手Next.js 15的app目录结构确实容易有点懵,不过你要区分公共导航和认证后导航的需求其实挺常见的,我来给你分享两种可行的实现方案,还有一些最佳实践参考~

方案一:在根布局中通过认证状态+路由判断切换导航

如果你不想拆分太多布局文件,可以直接在根layout.tsx里根据用户的认证状态和当前路由来渲染对应的导航栏。这种方式适合路由结构相对简单的场景。

关键思路:

  1. 先获取用户的认证状态(比如用NextAuth的useSession,或者你自己的状态管理方案)
  2. 结合当前路由路径,判断应该显示公共导航还是认证导航

代码示例:

首先,先创建两个独立的导航组件:

// app/components/PublicNavbar.tsx
export default function PublicNavbar() {
  return (
    <nav>
      <a href="/">首页</a>
      <a href="/login">登录</a>
      <a href="/signup">注册</a>
    </nav>
  )
}
// app/components/AuthenticatedNavbar.tsx
export default function AuthenticatedNavbar() {
  return (
    <nav>
      <a href="/dashboard">仪表盘</a>
      <a href="/profile">个人中心</a>
      <button>退出登录</button>
    </nav>
  )
}

然后在根布局里处理逻辑:

// app/layout.tsx
import { useSession } from 'next-auth/react'
import { usePathname } from 'next/navigation'
import PublicNavbar from './components/PublicNavbar'
import AuthenticatedNavbar from './components/AuthenticatedNavbar'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const { data: session } = useSession()
  const pathname = usePathname()

  // 定义公共路由列表
  const publicRoutes = ['/', '/login', '/signup']

  // 判断是否显示公共导航
  const shouldShowPublicNavbar = publicRoutes.includes(pathname) && !session
  // 判断是否显示认证导航
  const shouldShowAuthNavbar = !publicRoutes.includes(pathname) && session

  return (
    <html lang="zh-CN">
      <body>
        {shouldShowPublicNavbar && <PublicNavbar />}
        {shouldShowAuthNavbar && <AuthenticatedNavbar />}
        {children}
      </body>
    </html>
  )
}

方案二:用路由分组创建独立的公共/认证布局

这种方案更推荐,尤其是当你的路由越来越多的时候,通过Next.js的路由分组功能,可以把公共路由和认证路由分开,各自使用对应的布局,逻辑更清晰,也便于维护。

关键思路:

  1. 创建两个路由分组文件夹:app/(public) 和 app/(auth)
  2. 在每个分组里创建自己的layout.tsx,分别引入对应的导航栏
  3. 根布局只保留最基础的html和body结构,不处理导航逻辑

代码示例:

首先调整你的目录结构:

app/
├── (public)/
│   ├── layout.tsx
│   ├── page.tsx       # 首页(/)
│   ├── login/
│   │   └── page.tsx
│   └── signup/
│       └── page.tsx
├── (auth)/
│   ├── layout.tsx
│   ├── dashboard/
│   │   └── page.tsx
│   └── profile/
│       └── page.tsx
└── layout.tsx          # 根布局

然后编写公共分组的布局:

// app/(public)/layout.tsx
import PublicNavbar from '../components/PublicNavbar'

export default function PublicLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div>
      <PublicNavbar />
      {children}
    </div>
  )
}

编写认证分组的布局(这里可以加认证守卫,确保未登录用户无法访问):

// app/(auth)/layout.tsx
import { useSession } from 'next-auth/react'
import { redirect } from 'next/navigation'
import AuthenticatedNavbar from '../components/AuthenticatedNavbar'

export default function AuthLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const { data: session, status } = useSession()

  // 加载中状态可以显示加载动画
  if (status === 'loading') {
    return <div>加载中...</div>
  }

  // 如果未登录,重定向到登录页
  if (!session) {
    redirect('/login')
  }

  return (
    <div>
      <AuthenticatedNavbar />
      {children}
    </div>
  )
}

最后根布局只保留基础结构:

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  )
}

最佳实践建议

  • 优先选择路由分组方案:这种方式的代码结构更清晰,后期维护成本更低,尤其是当项目规模扩大时
  • 统一管理认证状态:推荐用NextAuth、Clerk这类成熟的认证库,避免自己手动处理会话逻辑容易出问题
  • 抽离导航组件:把公共和认证导航都做成独立组件,不要把导航代码直接写在布局里,提高复用性
  • 添加认证守卫:在认证路由的布局里加上登录校验,防止未登录用户直接访问受保护的页面

附上你提供的参考流程图:
WorkFlow Diagram

备注:内容来源于stack exchange,提问作者Shivani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 08:49:30