代码演示
如何引入
import { Nav } from '@douyinfe/semi-ui';
基本使用
通过传递 items
参数,你能够快速得到一个导航栏。
每个导航项目包括:
itemKey
:导航项目的唯一标识(必须)text
:导航文案icon
:导航图标
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconSetting } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
bodyStyle={{ height: 320 }}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
]}
onSelect={data => console.log('trigger onSelect: ', data)}
onClick={data => console.log('trigger onClick: ', data)}
/>
);
}
}
导航缩进
版本:>= 0.16.0
导航缩进目前仅对第一级导航有效果。
纯文案导航
如果导航项目没有传入 icon
字段,那么文案会自动向左填充。
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
class NavApp extends React.Component {
render() {
return (
<Nav
bodyStyle={{ height: 320 }}
defaultOpenKeys={[ 'job' ]}
items={[
{ itemKey: 'user', text: '用户管理' },
{ itemKey: 'union', text: '活动管理' },
{
itemKey: 'union-management',
text: '任务管理',
items: ['公告设置', '任务查询', '信息录入']
},
{
text: '任务平台',
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
]}
onSelect={data => console.log('trigger onSelect: ', data)}
onClick={data => console.log('trigger onClick: ', data)}
/>
);
}
}
定义头部和底部
开发者可能会经常定义 Logo 区域和收起按钮区域,Navigation 则提供了这样的容器方便开发者快速定义导航头部和底部,你仅需按要求传入 header 或 footer 即可。
对于 footer
,semi-ui 额外封装了一个收起功能按钮,开发者可以通过传递 collapseButton = true
开启此功能,不过该参数仅在 mode = "vertical"
(垂直导航)生效。
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconSetting, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
defaultOpenKeys={['job']}
bodyStyle={{ height: 320 }}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
]}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true,
}}
/>
);
}
}
导航样式定义
Navigation 目前提供了个两个参数用于定义导航样式:style
和 bodyStyle
,其中 style
用于定义导航组件最外层的样式,而 bodyStyle
用于定义导航列表的样式。(导航头部和导航底部则都接受各自的 style
参数)。
例如你需要一个导航列表可以滚动,导航头部和底部固定的导航组件,可以这么使用:
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconSetting, IconFolder, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
style={{ height: 520 }}
bodyStyle={{ height: 320 }}
defaultOpenKeys={['job', 'resource']}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
{
text: '资源管理',
icon: <IconFolder />,
itemKey: 'resource',
items: ['转盘配置', '转盘审核'],
},
]}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true,
}}
/>
);
}
}
JSX 写法
用户可以使用 JSX 写法定义导航头部、导航项以及导航底部。
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconStar, IconUser, IconUserGroup, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
bodyStyle={{ height: 320 }}
defaultOpenKeys={['user', 'union']}
onSelect={data => console.log('trigger onSelect: ', data)}
onClick={data => console.log('trigger onClick: ', data)}
>
<Nav.Header logo={<IconSemiLogo style={{ height: '36px', fontSize: 36 }} />} text={'Semi 运营后台'} />
<Nav.Item itemKey={'union'} text={'活动管理'} icon={<IconStar />} />
<Nav.Sub itemKey={'user'} text="用户管理" icon={<IconUser />}>
<Nav.Item itemKey={'active'} text={'活跃用户'} />
<Nav.Item itemKey={'negative'} text={'非活跃用户'} />
</Nav.Sub>
<Nav.Sub itemKey={'union-management'} text="任务管理" icon={<IconUserGroup />}>
<Nav.Item itemKey={'notice'} text={'任务设置'} />
<Nav.Item itemKey={'query'} text={'任务查询'} />
<Nav.Item itemKey={'info'} text={'信息录入'} />
</Nav.Sub>
<Nav.Footer collapseButton={true} />
</Nav>
);
}
}
配合 react-router 等路由组件
为了在使用 react-router 等路由组件时,能将 NavItem 包裹在路由组件提供的 Link 或者 NavLink 中来让用户点击 NavItem 时候触发路由组件的点击事件, 我们需要自定义渲染。
import { Link } from "react-router-dom";
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
() => {
return (
<Nav
renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
const routerMap = {
Home: "/",
About: "/about",
Dashboard: "/dashboard",
"Nothing Here": "/nothing-here"
};
return (
<Link
style={{ textDecoration: "none" }}
to={routerMap[props.itemKey]}
>
{itemElement}
</Link>
);
}}
items={[
{ itemKey: "Home", text: "Home" },
{ itemKey: "About", text: "About" },
{
text: "Sub",
itemKey: "Sub",
items: ["Dashboard", "Nothing Here"]
}
]}
></Nav>
);
}
导航方向
Navigation 目前提供两种方向的导航:
- 垂直方向(默认),
mode = "vertical"
- 水平方向,
mode = "horizontal"
特别注意的是,有一些功能(参数)仅在 mode = "vertical"
时有效:
isCollapsed
(导航收起到侧边)defaultOpenKeys
| openKeys
(指定默认的以及受控的展开子导航项 key 数组,这个参数仅在 mode = "vertical"
且 isCollapsed = false
有效)Footer
组件的 collapseButton
收起侧边栏功能按钮
竖直方向
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconStar, IconUser, IconUserGroup, IconSetting, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<div style={{ width: '100%' }}>
<Nav
bodyStyle={{ height: 320 }}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
itemKey: 'union-management',
text: '任务管理',
icon: <IconUserGroup />,
items: ['任务设置', '任务查询', '信息录入']
},
{
text: '公告管理',
icon: <IconSetting />,
itemKey: 'job',
items: ['推送管理', '已推送查询'],
},
]}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true,
}}
/>
</div>
);
}
}
水平方向
import React from 'react';
import { Nav, Avatar, Dropdown } from '@douyinfe/semi-ui';
import { IconStar, IconUser, IconUserGroup, IconSetting, IconEdit, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<div style={{ width: '100%' }}>
<Nav
mode={'horizontal'}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
itemKey: 'approve-management',
text: '审批管理',
icon: <IconEdit />,
items: [
'入驻审核',
{
itemKey: 'operation-management',
text: '运营管理',
items: [
'人员管理',
'人员变更'
]
}
]
},
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
]}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={
<Dropdown
position="bottomRight"
render={
<Dropdown.Menu>
<Dropdown.Item>详情</Dropdown.Item>
<Dropdown.Item>退出</Dropdown.Item>
</Dropdown.Menu>
}
>
<Avatar size="small" color='light-blue' style={{ margin: 4 }}>BD</Avatar>
<span>Bytedancer</span>
</Dropdown>
}
/>
</div>
);
}
}
水平加垂直
一般的平台设计会采取水平加垂直导航的模式,这里有一个比较常见的例子。
import React from 'react';
import { Nav, Avatar, Dropdown, Select, Button } from '@douyinfe/semi-ui';
import { IconStar, IconUser, IconUserGroup, IconSetting, IconEdit, IconLanguage, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
constructor() {
this.items = [
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
itemKey: 'union-management',
text: '任务管理',
icon: <IconUserGroup />,
items: ['公告设置', '任务查询', '信息录入']
},
{
itemKey: 'approve-management',
text: '审批管理',
icon: <IconEdit />,
items: [
'入驻审核',
{
itemKey: 'operation-management',
text: '运营管理',
items: [
'人员管理',
'人员变更'
]
}
]
},
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
];
this.renderHorizontal = this.renderHorizontal.bind(this);
this.renderVertical = this.renderVertical.bind(this);
}
renderHorizontal() {
return (
<Nav
mode={'horizontal'}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={
<>
<Select defaultValue='Chinese' style={{ width: 120, marginRight: 10 }} insetLabel={<IconLanguage />}>
<Select.Option value='Chinese'>中文</Select.Option>
<Select.Option value='English'>English</Select.Option>
<Select.Option value='Korean'>한국어</Select.Option>
<Select.Option value='Japanese'>日本語</Select.Option>
</Select>
<Button style={{ marginRight: 10 }}>切换至全球版</Button>
<Dropdown
position="bottomRight"
render={
<Dropdown.Menu>
<Dropdown.Item>详情</Dropdown.Item>
<Dropdown.Item>退出</Dropdown.Item>
</Dropdown.Menu>
}
>
<Avatar size="small" color='light-blue' style={{ margin: 4 }}>BD</Avatar>
<span>Bytedancer</span>
</Dropdown>
</>
}
/>
);
}
renderVertical() {
return (
<Nav
bodyStyle={{ height: 320 }}
items={this.items}
onSelect={key => console.log(key)}
footer={{
collapseButton: true,
}}
/>
);
}
render() {
return (
<>
{this.renderHorizontal()}
{this.renderVertical()}
</>
);
}
}
展开收起箭头位置
toggleIconPosition
设置 'left' 或 'right', 默认 right
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconSetting, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
toggleIconPosition={'left'}
defaultOpenKeys={['job']}
bodyStyle={{ height: 320 }}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
]}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true,
}}
/>
);
}
}
缩进限制
默认无缩进,需要导航项依据层级缩进请将 limitIndent 设置为 false
React Jsx 方式用 Nav.Item 传入导航项时 请手动给 Nav.Item 传入 level
props。
Object 方式 传入导航项时 无需关心 level
limitIndent 只在 竖直方向生效
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconSetting, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
limitIndent={false}
defaultOpenKeys={['job']}
bodyStyle={{ height: 320 }}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', {
text: '任务1',
icon: <IconSetting />,
itemKey: 'mission1',
items: ['任务2',
{
text: '任务3拆解',
icon: <IconSetting />,
itemKey: 'mission3',
items: ['子任务1', '子任务2'],
}
],
}],
},
]}
onSelect={key => console.log(key)}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true,
}}
/>
);
}
}
非受控属性
包括:
defaultSelectedKeys
(默认被选中的导航项 key
数组)defaultOpenKeys
(默认展开的导航项 key
数组,仅 mode = "vertical"
且 isCollapsed
| defaultIsCollapsed = false
的情况下有效)defaultIsCollapsed
(侧边栏默认是否收起,仅 mode = "vertical"
时有效)
import React from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconUserGroup, IconSetting, IconSemiLogo } from '@douyinfe/semi-icons';
class NavApp extends React.Component {
render() {
return (
<Nav
defaultOpenKeys={['job']}
defaultSelectedKeys={['信息录入']}
defaultIsCollapsed={true}
bodyStyle={{ height: 320 }}
items={[
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
itemKey: 'union-management',
text: '任务管理',
icon: <IconUserGroup />,
items: ['公告设置', '任务查询', '信息录入']
},
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
]}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true
}}
/>
);
}
}
受控属性
Navigation 组件提供了几个受控属性,配合各种回调,可以很轻松地控制导航。
目前受控的属性为:
isCollapsed
(侧边栏是否收起,仅 mode =" vertical"
时生效)selectedKeys
(当前选中的导航项 key
数组)openKeys
(当前展开的导航项数组,仅 mode = "vertical"
且 isCollapsed = false
有效)
对应的回调为:
onCollapseChange(isCollapsed: boolean): void
onSelect({ itemKey: string, selectedKeys: string[], domEvent: MouseEvent, isOpen: boolean }): void
onOpenChange({ itemKey: string, openKeys: string[], domEvent: MouseEvent, isOpen: boolean }): void
import React, { useMemo, useState } from 'react';
import { Nav } from '@douyinfe/semi-ui';
import { IconUser, IconStar, IconUserGroup, IconSetting, IconSemiLogo } from '@douyinfe/semi-icons';
function NavApp (props = {}) {
const [openKeys, setOpenKeys] = useState(['union-management', 'job']);
const [selectedKeys, setSelectedKeys] = useState(['用户任务查询']);
const [isCollapsed, setIsCollapsed] = useState(true);
const onSelect = data => {
console.log('trigger onSelect: ', data);
setSelectedKeys([...data.selectedKeys]);
};
const onOpenChange = data => {
console.log('trigger onOpenChange: ', data);
setOpenKeys([...data.openKeys]);
};
const onCollapseChange = isCollapsed => {
setIsCollapsed(isCollapsed);
};
const items = useMemo(() => [
{ itemKey: 'user', text: '用户管理', icon: <IconUser /> },
{ itemKey: 'union', text: '活动管理', icon: <IconStar /> },
{
itemKey: 'union-management',
text: '任务管理',
icon: <IconUserGroup />,
items: ['公告设置', '任务查询', '信息录入']
},
{
text: '任务平台',
icon: <IconSetting />,
itemKey: 'job',
items: ['任务管理', '用户任务查询'],
},
], []);
return (
<Nav
isCollapsed={isCollapsed}
openKeys={openKeys}
selectedKeys={selectedKeys}
bodyStyle={{ height: 360 }}
items={items}
header={{
logo: <IconSemiLogo style={{ height: '36px', fontSize: 36 }} />,
text: 'Semi 运营后台'
}}
footer={{
collapseButton: true
}}
onCollapseChange={onCollapseChange}
onOpenChange={onOpenChange}
onSelect={onSelect}
/>
);
}