涉及到路由,權限等等相關內容的部分,跟本文主旨關係不大,因此我將會在另一篇文章中詳述,混在一塊兒的話內容太多了html
基於element-ui的左側可伸縮的菜單
經過vuejs來開發支持展開收縮的菜單是很是簡單的,只須要v-if v-else便可簡單實現,下面我分步驟詳細講解過程,並在後續的系列文章中詳細講解權限菜單、路由過濾等等一些實用的技巧。固然還包括完整實現後臺管理頁面所要重點關注的細節。vue
如何把權限菜單展現出來呢?
首先,這是一個動態菜單,該顯示什麼樣的菜單須要從後端獲取,規則方面以下:html5
[ { 'label': '這個菜單', 'id': 001, 'parntid': 0 }, { 'label': '那個菜單', 'id': 002, 'parntid': 0 }, { 'label': '二個菜單', 'id': 003, 'parntid': 001 }, { 'label': '三個菜單', 'id': 003, 'parntid': 001 }, { 'label': '四個菜單', 'id': 003, 'parntid': 002 }, { 'label': '吳個菜單', 'id': 003, 'parntid': 002 } ]
注意:我這裏是用的兩級菜單,一樣的原理能夠很簡單的生成多級的。json中經過id來實現父子關聯,也能夠改爲多級的json,用child來表示子級,子級的子級。這樣也能夠很容易的生成多級的多級菜單。不過一般也就兩級或者三級。原理相同很容易擴展,若是不知道怎麼擴展歡迎加入qq羣:478694438來探討。
下面看一下菜單的展現,須要aside標籤,aside標籤是html5的標籤,沒見過aside ?沒關係換成div也行。先看效果,再看代碼(代碼看上去有點長,別被嚇着,我後面詳細講解):
這是收縮的狀態:
element-ui
這是展開的狀態:
json
<aside :class="collapsed?'menu-expanded':'menu-collapsed'"> <el-menu default-active="/ManageRole" v-if="collapsed" class="el-menu-vertical-demo" router> <template v-for="(item,index) in authMenu"> <el-submenu :index="index+''" v-if="item.parentPermissionCode==0"> <template slot="title"> <i :class="getIcon(item.permissionName)"> </i>{{item.permissionName}}</template> <el-menu-item v-for="child in authMenu" :index="child.uri" :key="child.permissionMark" v-if="item.permissionCode==child.parentPermissionCode"> <i :class="getIcon(child.permissionName)"> </i>{{child.permissionName}}</el-menu-item> </el-submenu> </template> </el-menu> <ul class="el-menu collapsed" ref="menuCollapsed" v-else> <li v-for="(item,index) in authMenu" v-if="item.parentPermissionCode==0" class="el-submenu item"> <template> <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"><i :class="getIcon(item.permissionName)"></i></div> <ul class="el-menu tipMenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"> <li v-for="child in authMenu" :key="child.uri" v-if="item.permissionCode==child.parentPermissionCode" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.uri)"><i :class="getIcon(child.permissionName)"></i> {{child.permissionName}}</li> </ul> </template> </li> </ul> <div class="changeState" @click="collapsed=!collapsed"> <i v-if="collapsed" class="iconfont icon-zuoyou1"></i> <i v-else class="iconfont icon-zuoyou"></i> </div> </aside>
來分析一下這些亂糟糟的代碼(這是我從源碼中截出來的因此看起來有點亂):
<el-menu>、<ul>、changeState這三個都是aside標籤下的同級的標籤,分別對應:展開狀態下的菜單、收縮狀態下的菜單、切換狀態的箭頭。
先看el-menu:後端
<el-menu default-active="/ManageRole" v-if="collapsed" class="el-menu-vertical-demo" router> <template v-for="(item,index) in authMenu"> <el-submenu :index="index+''" v-if="item.parentPermissionCode==0"> <template slot="title"> <i :class="getIcon(item.permissionName)"> </i>{{item.permissionName}}</template> <el-menu-item v-for="child in authMenu" :index="child.uri" :key="child.permissionMark" v-if="item.permissionCode==child.parentPermissionCode"> <i :class="getIcon(child.permissionName)"> </i>{{child.permissionName}}</el-menu-item> </el-submenu> </template> </el-menu>
collapsed這個值即爲判斷顯示展開仍是收縮狀態的開關。對照ul下的v-else看。經過一個v-for 循環除全部的父級菜單,再次循環尋找子級菜單中parentId==id的子菜單,做爲該父級菜單下的子菜單。這樣就實現了展開狀態下的菜單。
注意:圖標的問題,圖標能夠選擇從後端返回class,這樣作起來起來更簡單,我這裏是經過預設一個getIcon()函數在本地設置顯示,因爲圖標和路由面臨的是相同的實現,因此我會在路由跳轉相關的地方詳細解釋一下,應該在何種場景下選擇何種方式。ide
再看ul:函數
<ul class="el-menu collapsed" ref="menuCollapsed" v-else> <li v-for="(item,index) in authMenu" v-if="item.parentPermissionCode==0" class="el-submenu item"> <template> <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"><i :class="getIcon(item.permissionName)"></i></div> <ul class="el-menu tipMenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"> <li v-for="child in authMenu" :key="child.uri" v-if="item.permissionCode==child.parentPermissionCode" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.uri)"><i :class="getIcon(child.permissionName)"></i> {{child.permissionName}}</li> </ul> </template> </li> </ul>
這根element-ui就沒有關係了,簡單的ul li 實現。(路由相關的能夠展現忽略,我會在下一篇文章中詳細描述)優化
最後看:ui
<div class="changeState" @click="collapsed=!collapsed"> <i v-if="collapsed" class="iconfont icon-zuoyou1"></i> <i v-else class="iconfont icon-zuoyou"></i> </div>
經過collapsed 在v-if v-else中綁定視圖簡單實現了,開關功能。
寫在最後
這個功能看似簡單卻包含了vuejs的十幾個知識點。難倒了不少人,我之全部寫這篇文章,也是由於不少朋友,在此以前不斷的詢問我如何才能優雅的實現這個功能。固然了這隻一個完整的後臺管理的開始,我將會在後面的文章中繼續講解關於你們最關心的要不要使用addRoutes,如何使用addRoutes,不使用addRoutes的狀況下如何使用路由攔截來有沒的實現路由與權限的匹配,包括系統內部不一樣權限展現不一樣的操做界面的問題,固然了這是後話。若是有時間的話,我會把這個系列寫完,知道朋友們能獨立開發一個完整的vuejs的單頁面後臺管理程序。
另文中設計的代碼我將會上傳到討論羣中(478694438),不足之處優化共同探討。