专栏首页圣杰的专栏ABP入门系列(6)——定义导航菜单

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);
        }
}

至此,我们完成了对导航菜单的梳理和总结。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ASP.NET Core 借助 K8S 玩转容器编排

    由于最近在学习微服务,所以就基于之前docker的基础上把玩一下k8s(Kubernetes),以了解基本概念和核心功能。

    圣杰
  • 性能优化知多少

    1. 引言 最近一段时间,系统新版本要发布,在beta客户测试期间,暴露了很多问题,除了一些业务和异常问题外,其他都集中在性能上。有幸接触到这些性能调优的机会,...

    圣杰
  • Asp.net web api 知多少

    本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想...

    圣杰
  • 导航设计的15个原则

    为用户导航是每一位网站和app设计者的首要职责。毕竟用户一旦迷路,再炫酷的动效、再有趣的内容也都毫无意义。即使我们的网站和app中有搜索功能,也不能把搜索框当成...

    Shawn.W
  • 导航设计的10种模式

    导航设计的目的就是需要突出产品的核心,扁平化用户的任务路径。让用户能够顺利的在产品中畅行,让用户时刻清楚自己在应用中所处的位置,及如何前往目的页面。

    Shawn.W
  • wordpress导航

    搞wordpress没有几天,今晚准备分几个栏目写文章的时候可以分门别类,结果导航不知道才能显示出来我添加的子栏目。。。。纠结了于是找到摸索了半天终于找到了。下...

    苦咖啡
  • 菜单改版啦!我们该如何制定测试范围呢?

    由于菜单按钮位置有移动和功能有变更,所以需要回归菜单所有功能埋点统计,保证埋点统计正确,防止因菜单改版出现丢失埋点或埋点发送逻辑错误的问题。

    用户5521279
  • Pycharm主菜单学习

    于是,开始了第一步的学习----先从熟悉主菜单开始吧,总不能一打开软件,只会使用New、Run之类的简单操作指令吧!一开始翻译比较难,由于不习惯看英文,感觉好像...

    py3study
  • RS Meet DL(52)-基于注意力机制的用户行为建模框架ATRank

    本文来介绍一下阿里巴巴数据技术团队与北京大学共同提出的 ATRank ,ATRank是基于注意力机制的用户异构行为建模框架,可应用于推荐系统中,一起来了解一下吧...

    石晓文
  • 数据科学如何助力品牌推广?

    我曾经听到过这样一句话:“数据是客户的声音,数据科学是对这种声音的诠释”,我非常赞同这句话。数据科学可以帮助你找到许多问题的答案,这些问题是你的业务需求增长以及...

    iCDO互联网数据官

扫码关注云+社区

领取腾讯云代金券