想用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寬度沒有完全占滿父元素導致,可以通過設置有寬度的透明的右邊框解決。