董洪蒙
摘 要:前端開發(fā)是系統(tǒng)的臉面,國內(nèi)開源JS框架VUE表現(xiàn)優(yōu)異,很多前端開發(fā)者都采用它來實現(xiàn)業(yè)務(wù)系統(tǒng)界面。本篇文章來源于開發(fā)實戰(zhàn),如何實現(xiàn)一個精致、可拓展動態(tài)菜單,并闡述了開發(fā)思路、開發(fā)技術(shù),展示了精煉后的核心代碼,以期為前端開發(fā)者提供開發(fā)思路,共同集思廣益。
關(guān)鍵詞:VUE,vue-router,菜單,遞歸實現(xiàn)
VUE作為國產(chǎn)優(yōu)秀的構(gòu)建用戶界面的漸進(jìn)式JS框架,它是以數(shù)據(jù)驅(qū)動和組件化的思想構(gòu)建的。VUE與國外類似的框架相比,提供了更加簡潔的API,能很快地上手,是創(chuàng)建項目的首選前端框架。
筆者在為某政府機(jī)關(guān)開發(fā)一套小型業(yè)務(wù)系統(tǒng),采用VUE作為前端框架,且采用了vue-router路由組件、vuex數(shù)據(jù)組件,主體上使用螞蟻金服的ant design vue作為界面實現(xiàn)的組件庫。采用的業(yè)務(wù)系統(tǒng)非常流行的頂部-側(cè)邊-通欄布局,感覺其中的難點(diǎn)在于菜單的實現(xiàn),因為各個用戶因角色身份的不同,我們希望實現(xiàn)與其權(quán)限所對應(yīng)的菜單,由此必須通過AJAX技術(shù)動態(tài)從服務(wù)端取得動態(tài)菜單條目,并填充到界面中。假定通過axios從后端取得如下JSON菜單數(shù)據(jù):
"routes": [
"path": "/",
"component": () =>
import(/* webpackChunkName: "layout" */ "./layouts/BasicLayout"),
"children": [
{
"path": "/",
"redirect": "/dashboard/analysis"
},
{
"path": "/dashboard",
"name": "dashboard",
"meta": {
"icon": "dashboard",
"title": "儀表盤",
"authority": ["admin", "user"]
},
}
...
很明顯,是在后端開發(fā)時根據(jù)用戶不同,生成不同的菜單數(shù)據(jù),路徑下的meta字段,包括了authority,以表示顯示當(dāng)前表單項的相關(guān)有權(quán)限用戶。同時也很看出我們要采用VUE的vue-router插件,以控制點(diǎn)擊菜單時在layout中出現(xiàn)的不同content組件,實現(xiàn)SPA效果。因為里邊有children子菜單的出現(xiàn),所以要采用遞歸算法來動態(tài)生成相關(guān)的菜單表項,下面列出./layouts/SilderMenu/index.vue的模板實現(xiàn):
:selectedKeys="selectedKeys" :openKeys.sync="openKeys" mode="inline" :theme="theme"> v-if="!item.children" :key="item.path" @click="() => $router.push({ path: item.path, query: $route.query })" > ...
可見要在JS代碼中提供menuData等相關(guān)數(shù)據(jù):
data() {
const menuData = this.getMenuData(this.$router.options.routes)
return {
menuData,
}
},
getMenuData方法是獲取由服務(wù)端取得相關(guān)JSON數(shù)據(jù)渲染到實現(xiàn)菜單組件中,在methods中實現(xiàn):
getMenuData(routes = []) {
const menuData = []
for (let item of routes) {
if (item.meta && item.meta.authority) {
if (!check(item.meta.authority)) {
continue
}
}
if (item.name && !item.hideInMenu) {
const newItem = { ...item }
delete newItem.children
if (item.children && !item.hideChildrenMenu) {
newItem.children = this.getMenuData(item.children)
} else {
}
menuData.push(newItem)
} else if (
!item.hideInMenu &&
!item.hideChildrenMenu &&
item.children
) {
menuData.push(
...this.getMenuData(item.children),
)
}
}
return menuData
},
這段代碼十分復(fù)雜,有以下幾點(diǎn)值得注意:
* check(item.meta.authority)是檢查當(dāng)前用戶是否顯示該菜單的判斷;
* 通過JSON菜單數(shù)據(jù)的hideMenu, hideChildMenu值,以判斷是否顯示在菜單中,因為我們是通過vue-router來推送路徑的,有的路徑不需要再現(xiàn)在菜單中,如404、登錄注冊頁面等。
* 根據(jù)菜單數(shù)據(jù)中children數(shù)據(jù),采用遞歸調(diào)用方法,簡化了算法邏輯。
從./layouts/SilderMenu/index.vue中的實現(xiàn)中,我們還必須實現(xiàn)SubMenu子組件: ......
與SubMenu交互中,只需要通過VUE的props傳送已解析的菜單數(shù)據(jù)即可,即:menu-info="item"這段代碼。
菜單組件的實現(xiàn),主要采用了唐金洲Vue開發(fā)實戰(zhàn)中的開發(fā)思路,是這段業(yè)務(wù)系統(tǒng)開發(fā)中花費(fèi)時間較多的,邏輯也相對比較復(fù)雜的一段代碼,綜合運(yùn)用了多種前端開發(fā)的前沿知識,本人也無法貼出所有代碼,細(xì)講所有的知識點(diǎn),因為里邊涉及的東西太多了。有需要的可與我聯(lián)系,我們共同進(jìn)步和提高。
參考文獻(xiàn):
[1]唐金洲.Vue 開發(fā)實戰(zhàn)[EB/OL].北京:ant-design-vue官網(wǎng).2019-5-1
[2]肖睿,龍穎.Vue 企業(yè)開發(fā)實戰(zhàn)[M].北京:人民郵電出版社.2018-12-01