ABP⼊门系列(6)——定义导航菜单
完成了增删改查以及页⾯展⽰,这⼀节我们来为任务清单添加【导航菜单】。
在以往的项⽬中,⼤家可能会⼿动在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负责初始化菜单
NavigationConfiguration负责维护NavigationProvider的实现列表。
具体的NavigationProvider的实现
在对应的模块中注册具体的NavigtionProvider到INavigationConfiguration维护的列表中。
UserNavigationManager对NavigationManager进⾏了进⼀步的封装,根据⽤户和权限去创建和获取菜单。
在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);
}
}
⾄此,我们完成了对导航菜单的梳理和总结。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论