对于层级比较深的侧边菜单栏需求,常见的前端UI导航菜单栏组件的模板使用起来会比较复杂一点,主菜单和子菜单之间的嵌套关系会随之加大,你需要根据最大的层级去写你的模板内容,而且一旦层级加深,你的模板代码就需要再去维护一下。那么为了一劳永逸,就抽了时间写了一个纯数据驱动的侧边菜单栏组件,下面是最终实现的动态效果图:
上面是该组件的两种展开模式展示(是否只保持一个子菜单的展开),所使用的数据如下:
[
{
name: '菜单1'
},
{
name: '菜单2',
children: [
{name: '菜单2-1'},
{name: '菜单2-2'}
]
},
{
name: '菜单3',
children: [
{name: '菜单3-1', children: [{name: '菜单3-1-1'}]},
{name: '菜单3-2', children: [{name: '菜单3-2-1'}]},
]
},
{
name: '菜单4',
children: [
{name: '菜单4-1', children: [{name: '菜单4-1-1', children: [{name: '菜单4-1-1-1'}]}]}
]
}
]
想要把这种结构的数据渲染成具有上下级关系的菜单就需要用到递归组件的思想。思想有了之后,我们就可以来拆分组件的几个设计点了,具体如下:
- 组件的折叠动画:可以利用vue的transition过渡动画实现。
- 如何让所有子组件共享公共信息,例如当前的激活菜单:作为独立组件来说就不适合用vuex来做状态管理了,这里通过provide / inject, 让一个祖先组件向其所有子孙后代注入一个该祖先的实例依赖,这样就可以把公共信息放在这个祖先实例上。
其他需要实现的基本功能点罗列:
1.初始化菜单是否默认全部展开
2.是否只保持一个子菜单的展开
3.菜单栏宽度自由设置 (增加组件配置灵活性)
4. 指定显示的菜单名和唯一标识字段 (增加组件配置灵活性)
5. 指定默认激活的菜单
6. 是否使用vue-router的模式,启用该模式会在激活导航时以path字段值进行路由跳转
7. 等等......
有了设计点之后就可以开始码代码了,下面是菜单组件折叠动画的代码:
<script>
export default {
name: 'hb-menu-collapse-transition',
functional: true,
render(createElement, context) {
const data = {
props: {
mode: 'out-in',
duration: '300',
},
on: {
beforeEnter(el) {
el.classList.add('hb-menu-collapse')
if (!el.dataset) el.dataset = {}
el.dataset.oldPaddingTop = el.style.paddingTop
el.dataset.oldPaddingBottom = el.style.padding