☰
rsuite Sidenav 侧导航组件完全指南:从基础用法到源码级原理解析
2026/10/8 13:58:10 网站建设 项目流程
  • 前端
  • UI组件

【免费下载链接】rsuite

🧱 A suite of React components .

项目地址:https://gitcode.com/gh_mirrors/rs/rsuite
点击查看免费下载

导读

Sidenav 是 rsuite 中对页面侧边栏Nav组件的一层封装,专门用于构建后台管理系统、控制台类应用中最常见的"左侧导航 + 主内容区"布局。本文以官方文档为主体,完整覆盖 Sidenav 的获取方式、九类典型用法场景以及全部 Props 参数,并结合仓库源码剖析其 Context 状态管理、折叠动画与三种外观的实现原理,帮助你在实战中快速搭建可展开、可折叠、带子菜单与徽标的高质量侧边导航。

Sidenav 是什么

Sidenav(侧导航)是 rsuite 提供的用于页面侧边栏的导航组件,它本身并不独立实现导航逻辑,而是对Nav组件的封装,通过Sidenav.Body、Sidenav.Header、Sidenav.Footer等子组件划分出侧边栏的典型区块结构。源码注释中对它的定义非常明确:"TheSidenavcomponent is an encapsulation of the page sidebarNav"(参见 src/Sidenav/Sidenav.tsx)。

一个典型的 Sidenav 由Sidenav.Header(顶部区域,如 Logo、搜索框)、Sidenav.Body(主体,放置Nav导航内容)、Sidenav.Footer(底部区域,如折叠切换按钮)三部分构成。主组件默认渲染为<nav>元素,Body、Header、Footer等子组件默认渲染为<div>。

获取组件

Sidenav 支持两种引入方式,即从 rsuite 主包中整体导入,或按需单独引入组件及其样式:

// 方式一:从主包导入(Main) import { Sidenav, Nav } from 'rsuite'; // 方式二:单独引入(Individual) import Sidenav from 'rsuite/Sidenav'; import Nav from 'rsuite/Nav'; // (可选)按需引入组件样式 import 'rsuite/Sidenav/styles/index.css';

两种方式对应的完整代码由文档站点的 ImportGuide 组件自动生成(参见 docs/components/ImportGuide/ImportGuide.tsx)。按需引入时,组件样式文件遵循rsuite/<ComponentName>/styles/index.css的命名约定。

基础用法:默认侧边导航

最基础的场景是直接放置一组Nav.Item,并通过w属性(Box 宽度属性)控制侧边栏宽度:

import DashboardIcon from '@rsuite/icons/Dashboard'; import PeoplesIcon from '@rsuite/icons/Peoples'; import SettingIcon from '@rsuite/icons/Setting'; import PieChartIcon from '@rsuite/icons/PieChart'; import DataAuthorizeIcon from '@rsuite/icons/DataAuthorize'; import { Sidenav, Nav } from 'rsuite'; const App = () => ( <Sidenav w={240}> <Sidenav.Body> <Nav> <Nav.Item icon={<DashboardIcon />}>Overview</Nav.Item> <Nav.Item icon={<PeoplesIcon />}>Customers</Nav.Item> <Nav.Item icon={<PieChartIcon />}>Analytics</Nav.Item> <Nav.Item icon={<DataAuthorizeIcon />}>Security</Nav.Item> <Nav.Item icon={<SettingIcon />}>Settings</Nav.Item> </Nav> </Sidenav.Body> </Sidenav> ); ReactDOM.render(<App />, document.getElementById('root'));

每个Nav.Item都可以通过icon属性搭配 rsuite 图标库@rsuite/icons中的图标,形成"图标 + 文字"的经典侧边栏菜单项。完整示例见 docs/pages/components/sidenav/fragments/basic.md。

子菜单:多级导航结构

当菜单存在层级关系时,使用Nav.Menu包裹子项,并通过eventKey标识菜单项。defaultOpenKeys用于声明初始展开的菜单键值数组:

import { Sidenav, Nav } from 'rsuite'; import DashboardIcon from '@rsuite/icons/Dashboard'; import PeoplesIcon from '@rsuite/icons/Peoples'; import SettingIcon from '@rsuite/icons/Setting'; import PieChartIcon from '@rsuite/icons/PieChart'; import DataAuthorizeIcon from '@rsuite/icons/DataAuthorize'; const App = () => ( <Sidenav defaultOpenKeys={['3', '4']} w={240}> <Sidenav.Body> <Nav> <Nav.Item eventKey="1" icon={<DashboardIcon />}> Overview </Nav.Item> <Nav.Menu eventKey="2" title="Customers" icon={<PeoplesIcon />}> <Nav.Item eventKey="2-1">Users</Nav.Item> <Nav.Item eventKey="2-2">Groups</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="3" title="Analytics" icon={<PieChartIcon />}> <Nav.Item eventKey="3-1">Geo</Nav.Item> <Nav.Item eventKey="3-2">Devices</Nav.Item> <Nav.Item eventKey="3-3">Loyalty</Nav.Item> <Nav.Item eventKey="3-4">Visit Depth</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="4" title="Security" icon={<DataAuthorizeIcon />}> <Nav.Item eventKey="4-1">Users</Nav.Item> <Nav.Item eventKey="4-2">Roles</Nav.Item> <Nav.Item eventKey="4-3">Permissions</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="5" title="Settings" icon={<SettingIcon />}> <Nav.Item eventKey="5-1">Applications</Nav.Item> <Nav.Item eventKey="5-2">Channels</Nav.Item> <Nav.Item eventKey="5-3">Versions</Nav.Item> </Nav.Menu> </Nav> </Sidenav.Body> </Sidenav> );

Nav.Menu的eventKey同时也是其对应子菜单在openKeys/defaultOpenKeys中的标识:上述示例中['3', '4']表示初始展开 "Analytics" 与 "Security" 两个子菜单。完整示例见 docs/pages/components/sidenav/fragments/submenu.md。

从源码结构看,Sidenav 内部实际上把Nav.Menu渲染为SidenavDropdown组件(见 src/Sidenav/SidenavDropdown.tsx),子菜单的打开/关闭状态会同步写入 Sidenav 的openKeys。

分组标题:Sidenav.GroupLabel

当导航项很多、需要按业务模块分组时,使用Sidenav.GroupLabel定义分组标题。它通常配合Nav.Item的panel属性使用:

import { Sidenav, Nav } from 'rsuite'; import EventDetailIcon from '@rsuite/icons/EventDetail'; import TaskIcon from '@rsuite/icons/Task'; import PieChartIcon from '@rsuite/icons/PieChart'; import PeoplesIcon from '@rsuite/icons/Peoples'; import GearIcon from '@rsuite/icons/Gear'; const App = () => ( <Sidenav w={240}> <Sidenav.Body> <Nav> <Nav.Item panel> <Sidenav.GroupLabel>Workspace</Sidenav.GroupLabel> </Nav.Item> <Nav.Menu eventKey="1" title="Projects" icon={<EventDetailIcon />}> <Nav.Item eventKey="1-1">Overview</Nav.Item> <Nav.Item eventKey="1-2">All Projects</Nav.Item> <Nav.Item eventKey="1-3">Active Projects</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="2" title="Tasks" icon={<TaskIcon />}> <Nav.Item eventKey="2-1">My Tasks</Nav.Item> <Nav.Item eventKey="2-2">Assigned to Me</Nav.Item> </Nav.Menu> <Nav.Item panel> <Sidenav.GroupLabel>Management</Sidenav.GroupLabel> </Nav.Item> <Nav.Menu eventKey="3" title="Team" icon={<PeoplesIcon />}> <Nav.Item eventKey="3-1">Team Members</Nav.Item> <Nav.Item eventKey="3-2">Roles & Permissions</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="4" title="Settings" icon={<GearIcon />}> <Nav.Item eventKey="4-1">General Settings</Nav.Item> <Nav.Item eventKey="4-2">Security</Nav.Item> </Nav.Menu> </Nav> </Sidenav.Body> </Sidenav> );

完整示例见 docs/pages/components/sidenav/fragments/group.md。Sidenav.GroupLabel在样式上使用次级文字颜色(--rs-text-secondary)与较小的字号渲染(见 src/Sidenav/styles/index.scss 中.rs-sidenav-group-label规则),视觉上明显区别于可点击的菜单项。

Sidenav 顶部与底部

使用 Sidenav.Header 定义顶部内容

Sidenav.Header用来承载导航顶部的内容,例如品牌 Logo、搜索框等。下面的示例在头部放置了品牌标识与一个带搜索图标的输入框:

import DashboardIcon from '@rsuite/icons/Dashboard'; import SearchIcon from '@rsuite/icons/Search'; import { Sidenav, Nav, HStack, VStack, Input, InputGroup } from 'rsuite'; import { SiProtondb } from 'react-icons/si'; const Header = () => ( <VStack p="10px 10px 0 10px" spacing={12}> <HStack> <SiProtondb size={32} /> Brand </HStack> <InputGroup inside size="sm"> <InputGroup.Addon> <SearchIcon /> </InputGroup.Addon> <Input type="search" placeholder="Search here..." /> </InputGroup> </VStack> ); const App = () => ( <Sidenav w={240}> <Sidenav.Header> <Header /> </Sidenav.Header> <Sidenav.Body> <Nav> <Nav.Item icon={<DashboardIcon />}>Overview</Nav.Item> {/* ...更多菜单项 */} </Nav> </Sidenav.Body> </Sidenav> );

完整示例见 docs/pages/components/sidenav/fragments/header.md。

使用 Sidenav.Footer 定义底部内容

Sidenav.Footer用来承载导航底部的内容,最典型的就是折叠/展开导航的切换按钮。与Sidenav.Toggle搭配时,可以实现点击按钮即切换侧边栏展开状态:

import { Sidenav, Nav, HStack, VStack, Input, InputGroup, Box } from 'rsuite'; import DashboardIcon from '@rsuite/icons/Dashboard'; import SearchIcon from '@rsuite/icons/Search'; import { SiProtondb } from 'react-icons/si'; const Header = ({ expanded }) => { if (!expanded) { return ( <HStack justifyContent="center"> <SiProtondb size={32} /> </HStack> ); } return ( <VStack p="10px 10px 0 10px" spacing={12}> <HStack> <SiProtondb size={32} /> Brand </HStack> <InputGroup inside size="sm"> <InputGroup.Addon> <SearchIcon /> </InputGroup.Addon> <Input type="search" placeholder="Search here..." /> </InputGroup> </VStack> ); }; const App = () => { const [expanded, setExpanded] = React.useState(true); return ( <Box w={240}> <Sidenav expanded={expanded}> <Sidenav.Header> <Header expanded={expanded} /> </Sidenav.Header> <Sidenav.Body> <Nav> <Nav.Item icon={<DashboardIcon />}>Overview</Nav.Item> {/* ...更多菜单项 */} </Nav> </Sidenav.Body> <Sidenav.Footer> <Sidenav.Toggle onToggle={setExpanded} /> </Sidenav.Footer> </Sidenav> </Box> ); };

这个示例还展示了折叠状态下的自适应:当expanded为false时,头部只居中显示品牌图标、隐藏搜索框,底部显示折叠切换按钮。完整示例见 docs/pages/components/sidenav/fragments/footer.md。

Sidenav.Toggle在源码层面实现为IconButton,内部通过读取 Sidenav Context 拿到当前的expanded状态,点击时调用onToggle(!expanded, event)并同步触发onClick(见 src/Sidenav/SidenavToggle.tsx);它的aria-label会根据状态自动切换为Collapse或Expand,兼顾无障碍需求。

可控的展开与折叠导航

Sidenav 的展开状态既可以通过Sidenav.Toggle内部管理,也可以完全由外部受控。下面的示例用独立的Toggle开关组件控制expanded,同时让Nav的activeKey受控,形成完整的"选中项 + 展开状态"双向受控模式:

import { Sidenav, Nav, Toggle, Box } from 'rsuite'; import DashboardIcon from '@rsuite/icons/Dashboard'; import PeoplesIcon from '@rsuite/icons/Peoples'; import SettingIcon from '@rsuite/icons/Setting'; import PieChartIcon from '@rsuite/icons/PieChart'; import DataAuthorizeIcon from '@rsuite/icons/DataAuthorize'; const App = () => { const [expanded, setExpanded] = React.useState(false); const [activeKey, setActiveKey] = React.useState('1'); return ( <Box w={240}> <Toggle onChange={setExpanded} checked={expanded} checkedChildren="Expand" unCheckedChildren="Collapse" /> <hr /> <Sidenav expanded={expanded} defaultOpenKeys={['3', '4']}> <Sidenav.Body> <Nav activeKey={activeKey} onSelect={setActiveKey}> <Nav.Item eventKey="1" icon={<DashboardIcon />}> Overview </Nav.Item> <Nav.Menu eventKey="2" title="Customers" icon={<PeoplesIcon />}> <Nav.Item eventKey="2-1">Users</Nav.Item> <Nav.Item eventKey="2-2">Groups</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="3" title="Analytics" icon={<PieChartIcon />}> <Nav.Item eventKey="3-1">Geo</Nav.Item> <Nav.Item eventKey="3-2">Devices</Nav.Item> <Nav.Item eventKey="3-3">Loyalty</Nav.Item> <Nav.Item eventKey="3-4">Visit Depth</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="4" title="Security" icon={<DataAuthorizeIcon />}> <Nav.Item eventKey="4-1">Users</Nav.Item> <Nav.Item eventKey="4-2">Roles</Nav.Item> <Nav.Item eventKey="4-3">Permissions</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="5" title="Settings" icon={<SettingIcon />}> <Nav.Item eventKey="5-1">Applications</Nav.Item> <Nav.Item eventKey="5-2">Channels</Nav.Item> <Nav.Item eventKey="5-3">Versions</Nav.Item> </Nav.Menu> </Nav> </Sidenav.Body> <Sidenav.Footer> <Sidenav.Toggle onToggle={setExpanded} /> </Sidenav.Footer> </Sidenav> </Box> ); };

完整示例见 docs/pages/components/sidenav/fragments/collapsed.md。

关于expanded的受控与非受控:在源码中,openKeys(展开的菜单键值)通过useControlledHook 管理(见 src/Sidenav/Sidenav.tsx),即同时支持传入openKeys的受控模式和只传defaultOpenKeys的非受控模式;而整个 Sidenav 的展开/折叠则由expanded属性直接驱动,配合Transition组件(timeout={300})实现 300ms 的展开/折叠动画,动画期间分别挂载collapse-in/collapse-out/collapsing等 CSS 类。

自定义面板和分割线

在子菜单内部,可以通过在Nav.Item上设置panel和divider属性,自由组合出"分组标题 + 分割线"的精细排版,例如在同一个子菜单中分隔 "Reports" 与 "Settings" 两组内容:

import { Sidenav, Nav, HStack, VStack, Box } from 'rsuite'; import DashboardIcon from '@rsuite/icons/Dashboard'; import PeoplesIcon from '@rsuite/icons/Peoples'; import PieChartIcon from '@rsuite/icons/PieChart'; import { SiProtondb } from 'react-icons/si'; const Header = () => ( <VStack p="10px 10px 0 10px" spacing={12}> <HStack> <SiProtondb size={32} /> Brand </HStack> </VStack> ); const App = () => ( <Box w={240}> <Sidenav defaultOpenKeys={['3', '4']}> <Sidenav.Header> <Header /> </Sidenav.Header> <Sidenav.Body> <Nav> <Nav.Item eventKey="1" icon={<DashboardIcon />}> Overview </Nav.Item> <Nav.Item eventKey="2" icon={<PeoplesIcon />}> Customers </Nav.Item> <Nav.Menu eventKey="3" title="Analytics" icon={<PieChartIcon />}> <Nav.Item divider /> <Nav.Item panel> <Sidenav.GroupLabel>Reports</Sidenav.GroupLabel> </Nav.Item> <Nav.Item eventKey="3-1">Geo</Nav.Item> <Nav.Item eventKey="3-2">Devices</Nav.Item> <Nav.Item eventKey="3-3">Loyalty</Nav.Item> <Nav.Item eventKey="3-4">Visit Depth</Nav.Item> <Nav.Item divider /> <Nav.Item panel> <Sidenav.GroupLabel>Settings</Sidenav.GroupLabel> </Nav.Item> <Nav.Item eventKey="3-5">Applications</Nav.Item> <Nav.Item eventKey="3-6">Channels</Nav.Item> <Nav.Item eventKey="3-7">Versions</Nav.Item> </Nav.Menu> </Nav> </Sidenav.Body> </Sidenav> </Box> );

完整示例见 docs/pages/components/sidenav/fragments/divider-panel.md。divider渲染一条分割线,panel则把一个Nav.Item变为无交互的纯内容容器,用于承载Sidenav.GroupLabel之类的静态信息。

带徽标:用 Badge 显示数量

侧边导航经常需要提示"未读消息数""待办数量"等信息。将Badge组件嵌套进Nav.Item即可实现带徽标的菜单项。为了让徽标靠右对齐,示例中用HStack将文字与徽标两端分布:

import NoticeIcon from '@rsuite/icons/Notice'; import TaskIcon from '@rsuite/icons/Task'; import CalenderDateIcon from '@rsuite/icons/CalenderDate'; import HistoryIcon from '@rsuite/icons/History'; import { Sidenav, Nav, Badge, HStack } from 'rsuite'; const NavItem = ({ icon, children, badge }) => ( <Nav.Item icon={icon}> <HStack justifyContent="space-between" style={{ flex: 1 }}> {children} {badge} </HStack> </Nav.Item> ); const App = () => ( <Sidenav w={240}> <Sidenav.Body> <Nav> <NavItem icon={<NoticeIcon />} badge={<Badge content={15} />}> Notification </NavItem> <NavItem icon={<TaskIcon />} badge={<Badge content={6} />}> To-Do List </NavItem> <NavItem icon={<CalenderDateIcon />} badge={<Badge content="new" color="yellow" />}> Schedule </NavItem> <NavItem icon={<HistoryIcon />} badge={<Badge content="6.0.0" color="green" />}> Version History </NavItem> </Nav> </Sidenav.Body> </Sidenav> );

完整示例见 docs/pages/components/sidenav/fragments/with-badge.md。Badge的content既可以是数字也可以是文本,color属性可自定义徽标颜色(如yellow、green)。

外观:appearance 属性

appearance属性定义了 Sidenav 的三种视觉外观:

取值说明
default默认外观,使用默认背景色与文字色
inverse反转外观,使用深色背景与浅色文字,视觉上与默认外观形成强烈反差
subtle极简外观,背景透明,仅在悬停/选中时呈现底色,风格更轻盈

注意:在高对比度主题(High Contrast Mode)下,所有外观的表现都与default外观一致。

下面的示例用同一个受控组件结构渲染了三种外观的 Sidenav 并排对比,同时把openKeys、expanded、activeKey全部提升为受控状态:

import { Sidenav, Nav } from 'rsuite'; import DashboardIcon from '@rsuite/icons/Dashboard'; import PeoplesIcon from '@rsuite/icons/Peoples'; import SettingIcon from '@rsuite/icons/Setting'; import PieChartIcon from '@rsuite/icons/PieChart'; import DataAuthorizeIcon from '@rsuite/icons/DataAuthorize'; const styles = { width: 240, display: 'inline-table', marginRight: 10 }; const CustomSidenav = ({ appearance, openKeys, expanded, onOpenChange, onExpand, ...navProps }) => { return ( <div style={styles}> <Sidenav appearance={appearance} expanded={expanded} openKeys={openKeys} onOpenChange={onOpenChange} > <Sidenav.Body> <Nav {...navProps}> <Nav.Item eventKey="1" icon={<DashboardIcon />}> Overview </Nav.Item> <Nav.Menu eventKey="2" title="Customers" icon={<PeoplesIcon />}> <Nav.Item eventKey="2-1">Users</Nav.Item> <Nav.Item eventKey="2-2">Groups</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="3" title="Analytics" icon={<PieChartIcon />}> <Nav.Item eventKey="3-1">Geo</Nav.Item> <Nav.Item eventKey="3-2">Devices</Nav.Item> <Nav.Item eventKey="3-3">Loyalty</Nav.Item> <Nav.Item eventKey="3-4">Visit Depth</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="4" title="Security" icon={<DataAuthorizeIcon />}> <Nav.Item eventKey="4-1">Users</Nav.Item> <Nav.Item eventKey="4-2">Roles</Nav.Item> <Nav.Item eventKey="4-3">Permissions</Nav.Item> </Nav.Menu> <Nav.Menu eventKey="5" title="Settings" icon={<SettingIcon />}> <Nav.Item eventKey="5-1">Applications</Nav.Item> <Nav.Item eventKey="5-2">Channels</Nav.Item> <Nav.Item eventKey="5-3">Versions</Nav.Item> </Nav.Menu> </Nav> </Sidenav.Body> <Sidenav.Footer> <Sidenav.Toggle onToggle={onExpand} /> </Sidenav.Footer> </Sidenav> </div> ); }; const App = () => { const [activeKey, setActiveKey] = React.useState('1'); const [openKeys, setOpenKeys] = React.useState(['3', '4']); const [expanded, setExpand] = React.useState(true); return ( <> <CustomSidenav activeKey={activeKey} openKeys={openKeys} onSelect={setActiveKey} onOpenChange={setOpenKeys} expanded={expanded} onExpand={setExpand} /> <CustomSidenav activeKey={activeKey} openKeys={openKeys} onOpenChange={setOpenKeys} onSelect={setActiveKey} expanded={expanded} onExpand={setExpand} appearance="inverse" /> <CustomSidenav activeKey={activeKey} openKeys={openKeys} onOpenChange={setOpenKeys} onSelect={setActiveKey} expanded={expanded} onExpand={setExpand} appearance="subtle" /> </> ); };

完整示例见 docs/pages/components/sidenav/fragments/appearance.md。

源码实现要点:appearance在源码中并不会直接映射为 CSS 类,而是通过data-appearance数据属性下发(见 src/Sidenav/Sidenav.tsx 中的data-appearance={appearance}),样式表再据此命中.rs-sidenav[data-appearance='default'|'inverse'|'subtle']三组规则(见 src/Sidenav/styles/index.scss)。三种外观分别对应一组语义化的 CSS 变量,例如--rs-sidenav-default-bg、--rs-sidenav-inverse-bg、--rs-sidenav-subtle-hover-bg等,便于通过主题定制。样式文件中同时用high-contrast-mode混入(mixin)处理了高对比度主题下的外观统一问题,与文档中"高对比度主题下所有外观均与 default 一致"的说明相印证。

组件结构与状态管理原理

子组件组合关系

Sidenav 采用"主组件 + 静态子组件"的复合结构。主组件上挂载了 5 个可直接使用的子组件(见 src/Sidenav/Sidenav.tsx 中的Subcomponents定义):

  • Sidenav.Header:顶部区块
  • Sidenav.Body:主体区块
  • Sidenav.Footer:底部区块
  • Sidenav.GroupLabel:分组标题
  • Sidenav.Toggle:折叠切换按钮

此外,index.tsx还导出了Sidenav.Item、Sidenav.Dropdown、Sidenav.DropdownItem、Sidenav.DropdownToggle等内部组件(见 src/Sidenav/index.tsx)。不过在日常使用中,直接使用Nav.Item与Nav.Menu即可,Sidenav 会在内部将它们映射为对应的 Sidenav 变体。

Context 驱动的展开状态

Sidenav 通过SidenavContext向所有后代组件广播状态,Context 中包括openKeys、expanded、sidenav标记、onOpenChange回调等(见 src/Sidenav/SidenavContext.tsx)。当用户点击某个子菜单时,handleOpenChange会基于当前openKeys做增删操作——已存在则移除(折叠)、不存在则追加(展开),随后更新状态并触发onOpenChange(见 src/Sidenav/Sidenav.tsx)。

展开与折叠时的渲染差异

在SidenavDropdown中有一个关键分支:当 Sidenav 处于展开状态(sidenav.expanded为true)时,子菜单渲染为内联展开的ExpandedSidenavDropdown(二级菜单直接纵向铺开);当 Sidenav 折叠时,则切换为基于Menu的悬浮弹出层,点击菜单按钮后以浮层形式展示子菜单(见 src/Sidenav/SidenavDropdown.tsx)。折叠后的浮层菜单顶部还会渲染一个标题头(rs-dropdown-header),弥补折叠状态下无法显示父级菜单文字的不足。

样式层面,展开态(.rs-sidenav-collapse-in)下的子菜单使用原生折叠动画,菜单项支持 Ripple 水波纹效果;折叠态(.rs-sidenav-collapse-out)下菜单项只居中显示图标,文字通过sideNavFoldedText关键帧动画渐隐(见 src/Sidenav/styles/index.scss)。

测试覆盖情况

仓库为 Sidenav 提供了较为完整的测试用例(src/Sidenav/test/Sidenav.spec.tsx 及同目录下 Header、Body、Footer、Toggle、GroupLabel、Item 各自的 spec 文件),覆盖了默认渲染类名rs-sidenav、data-appearance属性、展开状态类名rs-sidenav-collapse-in、onSelect回调触发,以及 Sidenav 内 Dropdown 的展开/折叠动画切换等行为,可作为验证自定义用法是否正确的参考。

Props 完整参考

以下为官方文档提供的全部 Props 说明(Sidenav 各子组件于 6.0.0 版本新增的Toggle、Footer、GroupLabel已在表格中标注)。

<Sidenav>

属性名称类型(默认值)描述
appearance'default' | 'inverse' | 'subtle'('default')设置侧边导航的视觉外观样式
asElementType('div')自定义根组件的 HTML 元素类型
classPrefixstring('sidenav')组件 CSS 类名的前缀
defaultOpenKeysstring[]初始展开下拉菜单项的键值数组
expandedboolean(true)控制侧边导航的展开/折叠状态
onOpenChange(openKeys: string[], event) => void菜单项打开状态变化时的回调函数
openKeysstring[]受控的展开下拉菜单项的键值数组

补充说明:expanded默认值为true(源码中同样以expanded = true为默认值,见 src/Sidenav/Sidenav.tsx);as在官方 Props 表中记录的默认值为'div',而从源码实现看,主组件默认渲染为<nav>语义元素(as = 'nav'),子组件则默认渲染<div>。onOpenChange的回调签名还包含第二个参数event(React 合成事件),子菜单展开/收起时均会触发。

<Sidenav.Header>

属性名称类型(默认值)描述
asElementType('div')自定义头部组件的 HTML 元素类型
classPrefixstring('sidenav-header')头部组件 CSS 类名的前缀

<Sidenav.Body>

属性名称类型(默认值)描述
asElementType('div')自定义主体组件的 HTML 元素类型
classPrefixstring('sidenav-body')主体组件 CSS 类名的前缀

<Sidenav.Footer>

![][6.0.0]

属性名称类型(默认值)描述
asElementType('div')自定义底部组件的 HTML 元素类型
classPrefixstring('sidenav-footer')底部组件 CSS 类名的前缀

<Sidenav.Toggle>

![][6.0.0]

属性名称类型(默认值)描述
asElementType('button')自定义切换按钮的 HTML 元素类型
classPrefixstring('sidenav-toggle')切换按钮 CSS 类名的前缀
expandedboolean控制切换按钮的展开/折叠状态
onToggle(expanded: boolean) => void切换状态变化时的回调函数

<Sidenav.GroupLabel>

![][6.0.0]

属性名称类型(默认值)描述
asElementType('div')自定义分组标签的 HTML 元素类型
classPrefixstring('sidenav-group-label')分组标签 CSS 类名的前缀

实战小结

  • 骨架搭建:Sidenav+Sidenav.Body+Nav是最小可用组合;需要品牌区或操作区时再引入Sidenav.Header/Sidenav.Footer。
  • 多级导航:用Nav.Menu组织子菜单,配合defaultOpenKeys(非受控)或openKeys+onOpenChange(受控)管理展开状态。
  • 折叠交互:expanded控制整体折叠,Sidenav.Toggle或任意外部控件都可以驱动它;折叠后子菜单自动切换为悬浮浮层模式。
  • 视觉定制:appearance提供 default / inverse / subtle 三种开箱外观,高对比度主题下统一为 default 表现;更精细的配色可通过对应 CSS 变量在主题层覆盖。
  • 信息密度:分组标题、分割线、徽标可以组合出信息量充足且层次分明的导航结构。

如需查阅本文涉及的完整演示代码与源码,可继续浏览仓库中的 docs/pages/components/sidenav/fragments 目录(含 basic、submenu、group、header、footer、collapsed、divider-panel、with-badge、appearance、in-modal 等片段)以及 src/Sidenav 源码目录。

  • 前端
  • UI组件

【免费下载链接】rsuite

🧱 A suite of React components .

项目地址:https://gitcode.com/gh_mirrors/rs/rsuite
点击查看免费下载
上一篇:WinUtil:Windows系统优化与软件部署的终极指南
下一篇:零配置到全定制:FastAPI-MCP配置终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询