- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
导读
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') | 设置侧边导航的视觉外观样式 |
| as | ElementType('div') | 自定义根组件的 HTML 元素类型 |
| classPrefix | string('sidenav') | 组件 CSS 类名的前缀 |
| defaultOpenKeys | string[] | 初始展开下拉菜单项的键值数组 |
| expanded | boolean(true) | 控制侧边导航的展开/折叠状态 |
| onOpenChange | (openKeys: string[], event) => void | 菜单项打开状态变化时的回调函数 |
| openKeys | string[] | 受控的展开下拉菜单项的键值数组 |
补充说明:expanded默认值为true(源码中同样以expanded = true为默认值,见 src/Sidenav/Sidenav.tsx);as在官方 Props 表中记录的默认值为'div',而从源码实现看,主组件默认渲染为<nav>语义元素(as = 'nav'),子组件则默认渲染<div>。onOpenChange的回调签名还包含第二个参数event(React 合成事件),子菜单展开/收起时均会触发。
<Sidenav.Header>
| 属性名称 | 类型(默认值) | 描述 |
|---|---|---|
| as | ElementType('div') | 自定义头部组件的 HTML 元素类型 |
| classPrefix | string('sidenav-header') | 头部组件 CSS 类名的前缀 |
<Sidenav.Body>
| 属性名称 | 类型(默认值) | 描述 |
|---|---|---|
| as | ElementType('div') | 自定义主体组件的 HTML 元素类型 |
| classPrefix | string('sidenav-body') | 主体组件 CSS 类名的前缀 |
<Sidenav.Footer>
![][6.0.0]
| 属性名称 | 类型(默认值) | 描述 |
|---|---|---|
| as | ElementType('div') | 自定义底部组件的 HTML 元素类型 |
| classPrefix | string('sidenav-footer') | 底部组件 CSS 类名的前缀 |
<Sidenav.Toggle>
![][6.0.0]
| 属性名称 | 类型(默认值) | 描述 |
|---|---|---|
| as | ElementType('button') | 自定义切换按钮的 HTML 元素类型 |
| classPrefix | string('sidenav-toggle') | 切换按钮 CSS 类名的前缀 |
| expanded | boolean | 控制切换按钮的展开/折叠状态 |
| onToggle | (expanded: boolean) => void | 切换状态变化时的回调函数 |
<Sidenav.GroupLabel>
![][6.0.0]
| 属性名称 | 类型(默认值) | 描述 |
|---|---|---|
| as | ElementType('div') | 自定义分组标签的 HTML 元素类型 |
| classPrefix | string('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 .
相关推荐
TEN Framework 集成 EZAI 繁中 TTS 扩展:ezai_tw_tts_python 配置与实现全解析
TEN Framework 集成 EZAI 繁中 TTS 扩展:ezai_tw_tts_python 配置与实现全解析 本文档以 ezai_tw_tts_pyt
前端UI组件rsuite Pagination 分页组件完全指南:从基础用法到源码级原理解析
rsuite Pagination 分页组件完全指南:从基础用法到源码级原理解析 分页导航(Pagination)是长列表场景下最常见的交互组件之一,它允许列表
前端UI组件rsuite Card 卡片组件完全指南:从基础用法到源码级原理
rsuite Card 卡片组件完全指南:从基础用法到源码级原理 本文以 rsuite 开源仓库中的 Card(卡片)组件文档 docs/pages/compo
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考