如何在R Shiny中结合shiny.router实现二级导航栏?
实现shiny.router兼容二级导航的方案
1. 核心思路
放弃navbarPage/navbarMenu的整合尝试,手动构建Bootstrap风格的二级导航HTML结构,通过shiny.router的路由函数绑定导航链接,既保留路由的多页面管理能力,又能自由维护层级清晰的导航菜单,完全避开tabPanel的代码冗余问题。
2. 具体代码实现
第一步:定义各页面UI
先把需要的页面模块单独写好,方便后续扩展:
# 首页 home_page <- function() { fluidPage(h1("教材首页")) } # 第一章子页面1 chap1_page1 <- function() { fluidPage(h2("第一章 - 统计基础概念")) } # 第一章子页面2 chap1_page2 <- function() { fluidPage(h2("第一章 - 数据预处理")) } # 第二章子页面1 chap2_page1 <- function() { fluidPage(h2("第二章 - 线性回归模型")) } # 第二章子页面2 chap2_page2 <- function() { fluidPage(h2("第二章 - 模型诊断")) }
第二步:配置路由规则
用shiny.router::make_router建立路径和页面的对应关系:
library(shiny) library(shiny.router) router <- make_router( route("/", home_page()), route("/chap1/concepts", chap1_page1()), route("/chap1/preprocess", chap1_page2()), route("/chap2/regression", chap2_page1()), route("/chap2/diagnosis", chap2_page2()) )
第三步:手动编写二级导航栏
基于Bootstrap的下拉菜单组件写导航结构,每个链接用shiny.router::href()生成对应路由地址:
custom_navbar <- function() { tags$nav(class = "navbar navbar-expand-lg navbar-dark bg-primary", tags$a(class = "navbar-brand", href = href("/"), "统计教材网站"), # 移动端折叠按钮 tags$button(class = "navbar-toggler", type = "button", `data-toggle` = "collapse", `data-target` = "#mainNav", tags$span(class = "navbar-toggler-icon") ), tags$div(class = "collapse navbar-collapse", id = "mainNav", tags$ul(class = "navbar-nav mr-auto", # 首页项 tags$li(class = "nav-item", tags$a(class = "nav-link", href = href("/"), "首页") ), # 第一章下拉菜单 tags$li(class = "nav-item dropdown", tags$a(class = "nav-link dropdown-toggle", href = "#", role = "button", `data-toggle` = "dropdown", "第一章"), tags$div(class = "dropdown-menu", tags$a(class = "dropdown-item", href = href("/chap1/concepts"), "统计基础概念"), tags$a(class = "dropdown-item", href = href("/chap1/preprocess"), "数据预处理") ) ), # 第二章下拉菜单 tags$li(class = "nav-item dropdown", tags$a(class = "nav-link dropdown-toggle", href = "#", role = "button", `data-toggle` = "dropdown", "第二章"), tags$div(class = "dropdown-menu", tags$a(class = "dropdown-item", href = href("/chap2/regression"), "线性回归模型"), tags$a(class = "dropdown-item", href = href("/chap2/diagnosis"), "模型诊断") ) ) ) ) ) }
第四步:整合到Shiny应用
把导航栏和路由输出组合,补充Bootstrap依赖确保下拉菜单正常工作:
ui <- fluidPage( tags$head( # 加载Bootstrap样式和交互脚本 tags$link(rel = "stylesheet", href = "https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"), tags$script(src = "https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"), tags$script(src = "https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js") ), custom_navbar(), # 路由页面的输出容器 router$ui ) server <- function(input, output, session) { router$server(input, output, session) } shinyApp(ui, server)
3. 维护说明
后续新增章节或页面时,只需三步:
- 新增对应页面的UI函数
- 在
make_router中添加新的route()规则 - 在
custom_navbar里新增下拉菜单或菜单项,结构清晰易维护
内容的提问来源于stack exchange,提问作者annahuynhly
相关产品推荐
相关产品推荐

