在开发新的 Web 应用程序时,我们希望添加一个基于当前路由和参数动态生成的菜单组件。
而且MVC跳转页面时总是会刷新页面,导致当前选中的菜单栏高亮被取消,如何根据当前所在的页面高亮当前菜单栏?
一种解决办法是使用.NET CORE MVC中的 视图组件.
视图组件很强大,最适合用于菜单栏、动态导航栏等功能,当你在页面调用视图组件时,显示的数据取决于你传递的参数。
而且后续还需要根据用户角色等级来动态展示菜单栏入口,所以用视图组件很合适。
创建视图组件有诸多约定,文件放置目录、命名等。
首先建立菜单类MenuViewModel 以及子菜单类
public class Menu//子菜单类
{
public Guid ID { get; set; }
public Guid? ParentID { get; set; } //父类id
public string Content { get; set; }
public string IconClass { get; set; }
public string Url { get; set; }
public string SelectedStyle { get; set; }
public string SelectedClass { get; set; }
}
public class MenuViewModel//父菜单类
{
public Guid ID { get; set; }
public string Content { get; set; }//标题
public string IconClass { get; set; }//图标
public string Url { get; set; }
public string SelectedStyle { get; set; }//当前选中的样式
public string SelectedClass { get; set; }
public IList<NavViewModel> Children { get; set; }//子菜单
}
然后创建MenuViewModel类,这里写主要的业务逻辑,接收一个字符串参数controll,用于判断当前页面所在的是哪个控制器,由调用方传进来,这里的调用方是_Layout.cshtml
public class MenuViewModel: ViewComponent
{
//接收参数:控制器名称
public IViewComponentResult Invoke(
string controller)
{
string router = null;
switch (controller)//这里的主要作用就是判断当前是否被选中
{
case "Home":
router = "Home";
break;
case "User":
router = "User";
break;
}
var menu = new List<NavViewModel>();
menu.Add(new NavViewModel()
{
Content = "主页",
SelectedClass = (router == "Home") ? "layui-this" : null,
Url = "/Home",
ID = Guid.NewGuid()
}
);
menu.Add(new NavViewModel()
{
Content = "用户",
SelectedClass = (router == "User") ? "layui-this" : null,
Url = "/User",
ID = Guid.NewGuid()
}
);
return View(menu);
}
}
视图组件中的展示,因为我确定最多就一层子菜单,所以只嵌套了两层循环,如果有很多层子菜单就需要用递归了。需要注意我使用的是layui前端框架
@model List<MasterWebApi.Views.Shared.Components.Nav.NavViewModel>
<div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<ul class="layui-nav layui-nav-tree" lay-filter="nav">
@{
foreach (var item in Model)
{
if (item.Children != null)
{
<li class="layui-nav-item layui-nav-itemed">
<a href="javascript:;">@item.Content</a>
<dl class="layui-nav-child">
@foreach (var child in item.Children)
{
<dd class="@child.SelectedClass"><a href="@child.Url">@child.Content</a></dd>
}
</dl>
</li>
}
else
{
<li class="layui-nav-item @item.SelectedClass"><a href="@item.Url">@item.Content</a></li>
}
}
}
</ul>
</div>
</div>
在_layout.html中找一个合适的位置调用,传递当前controller的名字:
@await Component.InvokeAsync("Menu", @ViewContext.RouteData.Values["Controller"].ToString())
参考:
https://www.codeproject.com/Articles/1271364/Creating-a-Side-Menu-for-ASP-NET-Core-using-a-View