ABP入門系列(6)——定義導航菜單


ABP入門系列目錄——學習Abp框架之實操演練

完成了增刪改查以及頁面展示,這一節我們來為任務清單添加【導航菜單】。
在以往的項目中,大家可能會手動在layout頁面中添加一個a標簽來新增導航菜單,這也是一種方式,但是如果要針對不同用戶不同權限決定是否顯示某個菜單,那么直接在layout頁面中去控制就不方便了。
不過,ABP已經為大家考慮了這一點,集成了通用的創建和顯示菜單的方式。其主要代碼集成在Abp.Application.Navigation命名空間下,相應源碼在此
下面我們就來梳理下導航菜單是如何實現和使用。

一、如何使用Abp集成的導航菜單

針對我們的『任務清單』Deom,我們需要在導航欄上添加一個【Task List】的菜單入口。

1.打開web展現層,定位到App_Start/xxxNavigationProvider.cs。

    public class LearningMpaAbpNavigationProvider : NavigationProvider
    {
        public override void SetNavigation(INavigationProviderContext context)
        {
            context.Manager.MainMenu
                .AddItem(
                    new MenuItemDefinition(
                        "Home",
                        L("HomePage"),
                        url: "",
                        icon: "fa fa-home",
                        requiresAuthentication: true
                        )
                ).AddItem(
                    new MenuItemDefinition(
                        "Tenants",
                        L("Tenants"),
                        url: "Tenants",
                        icon: "fa fa-globe",
                        requiredPermissionName: PermissionNames.Pages_Tenants
                        )
                ).AddItem(
                    new MenuItemDefinition(
                        "Users",
                        L("Users"),
                        url: "Users",
                        icon: "fa fa-users",
                        requiredPermissionName: PermissionNames.Pages_Users
                        )
                ).AddItem(
                    new MenuItemDefinition(
                        "About",
                        L("About"),
                        url: "About",
                        icon: "fa fa-info"
                        )
                );
    }
}

該文件中默認定義了Home、Tenants、Users、About四個菜單。注意觀察的話,想必會注意到Home菜單設置了requiresAuthentication: true,即只有登陸后才會顯示該菜單。Tenants和Users菜單設置了requiredPermissionName屬性,即用戶具有指定的權限時才顯示菜單。About菜單沒有限制,默認顯示。
每一個菜單項都是一個MenuItemDefinition,其中主要包括Name(唯一名稱),DisplayName(本地化顯示名稱),Url(菜單跳轉),Icon(指定菜單圖標)。
解釋到這里,大家自己都可以依葫蘆畫瓢,新增菜單了。

2.添加[Task List]菜單項

AddItem(
  new MenuItemDefinition(
      "TaskList",
      L("Task List"),
      url: "Tasks/Index",
      icon: "fa fa-tasks",
      requiresAuthentication: true
  )

保存,刷新頁面即可看到新增的[Task List]菜單了。

PS:之所以頁面上會顯示為[Task List],是因為我們並沒有維護本地化資源文件。在對應的本地化配置文件中新增名為"Task List"的即可。比如在中文的本地化文件中添加
<text name="Task List" value="任務清單" />,重新啟站點,將語言切換為中文。


二、Abp集成的導航菜單的代碼結構

1.先來看看相關代碼的類型依賴關系圖
類型依賴關系圖
分析發現,abp集成的導航菜單實際上是應用了組合設計模式。
其中MenuDefinition為根節點,MenuItemDefinition為樹枝節點,其中MenuItemDefinition中也維護了一個List 的集合,當集合為空時,MenuItemDefinition即為樹葉節點。

2.從圖中可以看出,主要是由以下幾部分組成:

  • MenuDefinition/MenuItemDefinition:菜單/菜單項定義。其中菜單項包括Name(唯一名稱),DisplayName(本地化顯示名稱),Url(菜單跳轉),Icon(指定菜單圖標)。此外,可以通過指定RequiresAuthentication=true來限制菜單項只有對登錄用戶可見,同時也可以指定RequiredPermissionName來限定當用戶有某個權限時菜單才可見。
  • UserMenu/UserMenuItem:封裝了用於顯示給用戶的菜單/子菜單集合。
  • INavigationConfiguration/NavigationConfiguration:導航配置,維護了NavigationProvider的列表。
  • NavigationProvider:Provider模式(將api的定義和實現分離)。抽象類,定義了SetNavigation方法,在需要設置導航的項目中實現該類,並在對應的模塊中PreInitialize方法中注冊***NavigationProvider的實現。
  • INavigationManager/NavigationManager:其中接口中定義了一個Dictionary,用來存儲應用程序中定義的所有菜單項,和一個MainMenu。注入了對INavigationConfiguration的引用,以便在NavigationManager中的Initialize方法遍歷INavigationConfiguration配置的NavigationProvider列表進行菜單的初始化。
    IUserNavigationManager/UserNavigationManager:是對NavigationManager的一次封裝。其中接口中定義了GetMenuAsync的重載方法,用來獲取指定用戶的菜單。
  • INavigationProviderContext/NavigationProviderContext:封裝了INavigationManager的上下文類,用於傳參。

三、Abp集成的導航菜單的具體實現

核心邏輯:NavigationManager遍歷NavigationConfiguration中維護的NavigationProvider列表,並調用NavigationProvider實現的SetNavigation方法來完成導航菜單的初始化。

NavigationManager負責初始化菜單
NavigationManager.cs

NavigationConfiguration負責維護NavigationProvider的實現列表。
NavigationConfiguration.cs

具體的NavigationProvider的實現
xxxxNavigationProvider.cs

在對應的模塊中注冊具體的NavigtionProvider到INavigationConfiguration維護的列表中。
xxxxAbpWebModule.cs

UserNavigationManager對NavigationManager進行了進一步的封裝,根據用戶和權限去創建和獲取菜單。
IUserNavigationManager.cs

在LayoutController中,通過注入對IUserNavigationManager的引用,來獲取菜單,並由_TopMenu分部頁進行最終呈現。

public class LayoutController : LearningMpaAbpControllerBase
    {
        private readonly IUserNavigationManager _userNavigationManager;
        private readonly ISessionAppService _sessionAppService;
        private readonly IMultiTenancyConfig _multiTenancyConfig;
        private readonly ILanguageManager _languageManager;

        public LayoutController(
            IUserNavigationManager userNavigationManager, 
            ISessionAppService sessionAppService, 
            IMultiTenancyConfig multiTenancyConfig,
            ILanguageManager languageManager)
        {
            _userNavigationManager = userNavigationManager;
            _sessionAppService = sessionAppService;
            _multiTenancyConfig = multiTenancyConfig;
            _languageManager = languageManager;
        }

        [ChildActionOnly]
        public PartialViewResult TopMenu(string activeMenu = "")
        {
            var model = new TopMenuViewModel
                        {
                            MainMenu = AsyncHelper.RunSync(() => _userNavigationManager.GetMenuAsync("MainMenu", AbpSession.ToUserIdentifier())),
                            ActiveMenuItemName = activeMenu
                        };

            return PartialView("_TopMenu", model);
        }
}

至此,我們完成了對導航菜單的梳理和總結。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM