無論用什么框架,第一件事情就是實現(xiàn)動態(tài)菜單,從數(shù)據(jù)庫中讀取菜單配置項輸出前臺,網(wǎng)上翻了一大堆翻譯文檔,也看了官方英文文檔,關(guān)鍵點在于如何實現(xiàn)NavigationProvider
和在前端調(diào)用abp.nav.menus.MainMenu
。
public class UiMenu : FullAuditedEntity<int>, IMustHaveTenant { public int Pid { get; set; } [Required] [StringLength(50)] public string Name { get; set; } [Required] [StringLength(50)] public string DisplayName { get; set; } [Required] [StringLength(50)] public string MenuType { get; set; } [StringLength(200)] public string Path { get; set; } [StringLength(500)] public string CustomData { get; set; } [StringLength(200)] public string Remark { get; set; } public string Icon { get; set; } public string Action { get; set; } public int Order { get; set; } public int TenantId { get; set; } }
在Core項目里新建文件夾Navigations
,新建類MyNavigationProvider
,需繼承NavigationProvider
。
如下實現(xiàn)UiMneu的倉儲操作對象
private readonly IRepository<UiMenu> _repository; public MyNavigationProvider(IRepository<UiMenu> repository) { _repository = repository; }
然后重寫SetNavigation
。
var allMenus = _repository.GetAllList(); foreach (var item in allMenus) { if (item.Pid>0) { //子項 context.Manager.MainMenu.GetItemByName(allMenus.Find(p => p.Id == item.Pid).Name).AddItem( new MenuItemDefinition( item.Name, new LocalizableString(item.DisplayName, MyConsts.LocalizationSourceName), url: item.Path, icon: item.Icon, isVisible: item.IsDeleted, requiredPermissionName: "" ) ); } else { //父級菜單 context.Manager.MainMenu.AddItem(new MenuItemDefinition( item.Name, new LocalizableString(item.DisplayName, MyConsts.LocalizationSourceName), url: item.Path, icon: item.Icon, isVisible:item.IsDeleted, requiredPermissionName:""//配置權(quán)限,可在UiMenu表中新加字段配置 )); } }
至于如何對菜單表進行增刪改查維護,不是本篇主題,故略過。
前端實現(xiàn)的主要是依靠官方提供的方法abp.nav.menus.MainMenu
import main from '../views/main.vue'//import ParentView from '@/components/parent-view'// 加載路由菜單,從localStorage拿到路由,在創(chuàng)建路由時使用// @函數(shù): 引入組件export const lazyLoadingCop = file => require('../views' + file + '.vue').defaultclass RouterHelper { dynamicRouterAdd(): Array<Router> { let dynamicRouter = [] window.abp.nav.menus.MainMenu.items.forEach(el => { let obj = { path: '/' + el.name, name: el.name, icon: el.icon, permission: undefined, meta: { title: el.displayName }, component: 'main', children: [], } if (el.items.length > 0) { el.items.forEach(child => { obj.children.push({ path: child.name, name: child.name, icon: child.icon, permission: undefined, meta: { title: child.displayName }, component: child.url, children: null, }) }) dynamicRouter.push(obj) } else { dynamicRouter.push({ path: '/' + el.items[0].name, name: el.items[0].name, icon: el.items[0].icon, permission: undefined, meta: { title: el.items[0].displayName }, component: el.items[0].url, children: [], }) } }); dynamicRouter = this.filterAsyncRouter(dynamicRouter) return dynamicRouter } // @函數(shù): 遍歷后臺傳來的路由字符串,轉(zhuǎn)換為組件對象 filterAsyncRouter(asyncRouterMap) { const accessedRouters = asyncRouterMap.filter(route => { if (route.component) { if (route.component === 'main' || route.component.name === 'main') { // Main組件特殊處理 route.component = main } // else if (route.component === 'parentView') { // parentView組件特殊處理 // route.component = ParentView // } else { route.component = lazyLoadingCop(route.component) } } if (route.children && route.children.length) { route.children = this.filterAsyncRouter(route.children) } return true }) return accessedRouters }}const routerHelper = new RouterHelper();export default routerHelper;
parentView
為多級菜單,如果有需求可以使用,該組件摘自iView admin 2.0
解釋:
循環(huán)abp.nav.menus.MainMenu.items
,將其格式轉(zhuǎn)換為Router
。方便菜單調(diào)用。
找到router/index.ts,
在beforeEach
方法里添加如下代碼
let dyRouters = RouterHelper.dynamicRouterAdd() dyRouters.forEach(element => { appRouters.push(element); }); router.addRoutes(appRouters)
注意引用 import RouterHelper from '../lib/router-util'
一開始沒有絲毫頭緒,后臺參照使用iview admin時構(gòu)建的方法進行嘗試,加之剛剛接觸typescript,用起來不是特別順手,問題的關(guān)鍵在于router/router.ts
->appRouters處無法獲得abp.nav.menus.MainMenu.items
在store/modules/app里雖然可以獲取,但是router中不存在,無法正常點擊跳轉(zhuǎn),taglist同樣也無從獲取。
最終想到這種不是很完美的方法,前端仍然需要進行循環(huán)轉(zhuǎn)換Model。但終歸是實現(xiàn)了動態(tài)菜單,可以進行下一步操作了。