Nav 侧边导航
分组导航。不依赖路由——选中值就是一个普通字符串。
基础用法
当前选中:/overview
vue
<script setup>
import { ref } from 'vue'
const active = ref('/overview')
const groups = [
{
key: 'main',
title: '主要',
items: [
{ value: '/overview', label: '概览' },
{ value: '/docs', label: '文档', badge: '新' }
]
}
]
</script>
<template>
<SrNav v-model="active" :groups="groups" />
</template>为什么不依赖路由
组件的选中值就是一个普通字符串,不读 useRoute()、也不调用 router.push()。 点击时只发 update:modelValue,跳不跳、怎么跳由宿主决定。
这样做的理由:
- 不绑定具体路由库。Vue Router、Nuxt 的文件路由、甚至纯 hash 锚点, 都能接;
- 可以当纯选择器用。有些场景它就是「选一个分类」,并不需要跳转;
- 避免在组件库里 import
vue-router——那会让不用路由的项目 也被迫装上一个 peer dependency。
接路由的写法:
vue
<script setup>
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const active = computed({
get: () => route.path,
set: (path) => router.push(path)
})
</script>
<template>
<SrNav v-model="active" :groups="groups" />
</template>折叠
collapsible 显示折叠按钮,collapsed 控制状态(配合 v-model:collapsed)。
折叠状态:已展开
vue
<SrNav v-model="active" v-model:collapsed="collapsed" :groups="groups" collapsible />折叠后只显示图标,有子项时父项变为浮层入口,子项在图标右侧弹出。
折叠态需要图标
折叠后文字全部隐藏,若导航项没有图标,用户会面对一排无法区分的方块。 SrNavItem 支持 icon 插槽——需要折叠功能时务必给每项配上图标。
二级菜单
children 支持一层子项。展开态下点击父项就地展开,不跳转。
vue
const groups = [
{
items: [
{
value: '/guide',
label: '指南',
children: [
{ value: '/guide/start', label: '快速开始' },
{ value: '/guide/theme', label: '主题定制' }
]
}
]
}
]不支持无限嵌套是有意的
导航的可用性随层级急剧下降——三级以上的导航,用户既看不清当前位置, 也很难预测点击后会去哪。
超过两级应该改用 SrTree:树的展开状态一目了然,也更适合表达结构。
徽标与禁用
vue
{ value: '/docs', label: '文档', badge: '新' } // 短文本徽标
{ value: '/changelog', label: '更新日志', badge: 3 } // 数字徽标
{ value: '/archived', label: '已归档', disabled: true }尺寸与宽度
vue
<SrNav :groups="groups" size="sm" width="200px" collapsed-width="56px" />Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | number | — | 当前选中的项 |
groups | SrNavGroup[] | [] | 分组数据 |
collapsible | boolean | false | 是否显示折叠按钮 |
collapsed | boolean | false | 是否处于折叠态 |
width | string | '240px' | 展开宽度 |
collapsedWidth | string | '56px' | 折叠宽度 |
size | 'sm' | 'md' | 'md' | 尺寸 |
数据结构
ts
interface SrNavGroup {
key?: string // 折叠时的分组标识,建议显式传入
title?: string // 分组标题,不传则不渲染标题行
items: SrNavItem[]
}
interface SrNavItem {
value: string | number
label: string
badge?: string | number
disabled?: boolean
children?: SrNavItem[] // 仅支持一层
}事件
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | 选中值 | 选中项变化 |
update:collapsed | boolean | 折叠状态变化 |
无障碍
- 用
<nav>语义,并带aria-label说明这是什么导航 - 当前项带
aria-current="page",读屏用户能定位自己在哪 - 折叠按钮带
aria-expanded与aria-label(「展开导航」/「收起导航」) - 二级菜单的父项带
aria-haspopup与aria-expanded