想用iview做一個可以伸縮的側邊菜單欄,效果如下:
1.側邊欄收縮前:可以通過點擊菜單分類展開子菜單項;
2.可以讓用戶點擊圖標動態收縮菜單欄;
3.側邊欄收縮后:只顯示菜單分類的圖標,鼠標放置在菜單分類上后右側展示子菜單項目。

一、初探
仔細看了iview的菜單組件,菜單組件本身不支持伸縮(element UI、antd是有現成組件的),看了一下layout組件(https://www.iviewui.com/components/layout)可以實現動態收縮側邊欄(側邊欄伸縮同時隱藏菜單項的文字實現菜單收縮)。但這種方法只是單純的將一級分類菜單隱藏了,示例中是只有一級菜單,自己套入二級菜單后慘不忍睹。
二、研究思考
百度了一堆iview伸縮菜單的實現方式,發現有的人在側邊欄收縮后二級菜單能正常顯示,心里就想莫非這些人是用是收費的UI Pro,於是就打開了UI Pro的網址(https://pro.iviewui.com/pro/introduce)。你猜怎么着!Pro的網站側邊欄就是我們想要的效果,翻了一下Pro的組件也沒有可伸縮的菜單組件啊~ 看來只能自己實現了,不過好在可以拿Pro的的做參考研究。
觀察發現側邊欄收起來后:1)當菜單分類下沒有子菜單時,右邊彈出的是一個tooltip組件 2)當菜單分類下有子菜單時,右邊彈出的是dropdown組件。
三、實現
將菜單放到menu數組中,通過children屬性設置菜單分類的子菜單,template部分對menu進行遍歷,通過判斷當前條件(側邊欄是否收縮、當前分類是否有子菜單)放置不同的組件,實現側邊菜單的動態伸縮展示。存在如下4種情況:
1.菜單展開時,當前菜單分類沒有子菜單,使用MenuItem組件。
2.菜單展開時,當前菜單分類有子菜單,使用Submenu組件。
3.菜單收縮時,當前菜單沒有子菜單,使用Tooltip組件。
4.菜單收縮時,當前菜單有子菜單,使用Dropdown組件。
template部分代碼如下
<Menu
active-name="home"
:open-names="['home']"
:theme="menuTheme"
width="auto"
:class="menuitemClasses"
accordion
>
<template v-for="(item, componentIndex) in menu">
<!-- 展開並且有子菜單 -->
<Submenu v-if="!isCollapsed && item.children.length" v-bind:key="componentIndex" :name="componentIndex">
<template slot="title">
<Icon :type="item.icon" />
<span>{{ item.name }}</span>
</template>
<MenuItem v-for="(children, index) in item.children" :key="index" :name="children.to" :to="children.to">
{{ children.name }}
</MenuItem>
</Submenu>
<!-- 展開但沒有子菜單 -->
<MenuItem v-else-if="!isCollapsed" :name="item.to" :to="item.to" v-bind:key="componentIndex">
<Icon :type="item.icon" />
<span>{{ item.name }}</span>
</MenuItem>
<!-- 不展開有子菜單 -->
<Dropdown v-else-if="isCollapsed && item.children.length" v-bind:key="componentIndex" placement="right-start" class="menu-dropdown">
<MenuItem :name="item.to" :to="item.to" >
<Icon :type="item.icon" />
<span>{{ item.name }}</span>
</MenuItem>
<DropdownMenu slot="list">
<DropdownItem v-for="(children, index) in item.children" :key="index" style="padding: 0 0; background-color:#515a6e;">
<MenuItem :name="children.to" :to="children.to">{{ children.name }}</MenuItem>
</DropdownItem>
</DropdownMenu>
</Dropdown>
<!-- 不展開無子菜單 -->
<Tooltip v-else-if="isCollapsed" :content="item.name" placement="right" v-bind:key="componentIndex">
<MenuItem :name="item.to" :to="item.to">
<Icon :type="item.icon" />
<span>{{ item.name }}</span>
</MenuItem>
</Tooltip>
</template>
</Menu>
data部分菜單定義代碼如下
data() {
return {
isCollapsed: false,
keepAliveList: [],
title: "Home",
showSettingPage: false,
showSuggestionPage: false,
menu: [
{
name: "主頁",
to: "home",
icon: "md-apps",
children: []
},
{
name: "菜單分類1",
to: "user",
icon: "ios-create-outline",
children: [
{
name: "子菜單1",
to: "user"
},
{
name: "子菜單2",
to: "menu"
},
{
name: "子菜單3",
to: "shared_report"
},
]
},
{
name: "菜單分類2",
to: "user2",
icon: "ios-archive-outline",
children: [
{
name: "子菜單2-1",
to: "firewall"
},
{
name: "子菜單2-2",
to: "navi_page"
}
]
}
]
};
},
四、優化
能夠看到這里,說明你也是個前端高手。當側邊欄收縮時,還有如下幾個優化項大概提一下,給個方向:
1.dropdown menu背景顏色與側邊欄不一致。
2.dropdown menu上放置鼠標后,有其他顏色出現。—— menuItem的li元素有padding
3.dropdown menu顯示區域與側邊菜單有重疊。—— dropdown menu中的ivu-dropdown-rel寬度沒有完全占滿父元素導致,可以通過設置有寬度的透明的右邊框解決。
