Blazor 是一个用于使用 .NET 生成交互式客户端 Web UI 的框架:
- 使用 C# 代替 JavaScript 来创建丰富的交互式 UI。
- 共享使用 .NET 编写的服务器端和客户端应用逻辑。
- 将 UI 呈现为 HTML 和 CSS,以支持众多浏览器,其中包括移动浏览器。
使用 .NET 进行客户端 Web 开发可提供以下优势:
- 使用 C# 代替 JavaScript 来编写代码。
- 利用现有的 .NET 库生态系统。
- 在服务器和客户端之间共享应用逻辑。
- 受益于 .NET 的性能、可靠性和安全性。
- 始终高效支持 Windows、Linux 和 macOS 上的 Visual Studio。
- 以一组稳定、功能丰富且易用的通用语言、框架和工具为基础来进行生成。
一、网站下载Inspinia 模板
下载后的静态页模板
建立 ASP.NET Core Blazor 项目
如果是服务器模式 把js和css核心复制进去,放置位置是很目录的 _Host.cshtml。
如果是WebAssembly 模式,放置位置是_wwwroot文件下面的index.html页面。
二、建立简易的菜单结构(模拟传统的MVC)
1.一级菜单 【客户管理】,二级菜单分别是 添加客户 和 客户列表。
添加客户 对应路由地址 Customer/Add
客户列表 对应路由地址 Customer/List
2.一级菜单 【产品管理】,二级菜单分别是 添加产品 和 产品列表。
添加产品 对应路由地址 Product/Add
产品 列表 对应路由地址 Product/List
三、实现菜单选中
下面引自 官方文档解释
NavLink 组件
创建导航链接时,请使用 NavLink
组件来代替 HTML hyperlink 元素(<a>
)。 @No__t_0 组件的行为类似于 <a>
元素,只不过它会根据其 href
是否匹配当前 URL 来切换 active
CSS 类。 @No__t_0 类可帮助用户了解在显示的导航链接中哪一页是活动页。
以下 NavMenu
组件创建一个演示如何使用 NavLink
组件的启动导航栏:
<div class="@NavMenuCssClass" @onclick="@ToggleNavMenu">
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="MyComponent" Match="NavLinkMatch.Prefix">
<span class="oi oi-plus" aria-hidden="true"></span> My Component
</NavLink>
</li>
</ul>
</div>
可以将两个 NavLinkMatch
选项分配给 <NavLink>
元素的 Match
属性:
- 如果
NavLink
在与整个当前 URL 匹配时处于活动状态,则NavLinkMatch.All
–。 NavLinkMatch.Prefix
(默认值),当NavLink
与当前 URL 的任何前缀匹配时,– 处于活动状态。
在前面的示例中,Home NavLink
href=""
与 home URL 匹配,并且仅接收应用的默认基路径 URL (例如 https://localhost:5001/
)中的 active
CSS 类。 第二个 NavLink
在用户访问具有 MyComponent
前缀的任何 URL (例如 https://localhost:5001/MyComponent
和 https://localhost:5001/MyComponent/AnotherSegment
)时接收 active
类。
其他 NavLink
组件特性会传递到呈现的定位点标记。 在下面的示例中,NavLink
组件包含 target
属性:
<NavLink href="my-page" target="_blank">My page</NavLink>
呈现以下 HTML 标记:
<a href="my-page" target="_blank" rel="noopener noreferrer">My page</a>
当前点击菜单父层 li 设置了active 实现当前选中,且同级元素UL 也是设置 class 添加in样式才能展开。
所以 Navlink现在不能用了,所以需要用到 NavigationManager
组件来监听路由切换。
在母版页 MainLayout.razor 写全局监听事件。
@inherits LayoutComponentBase @inject NavigationManager navigationManager @inject IJSRuntime jsRuntime <div id="wrapper"> <nav class="navbar-default navbar-static-side" role="navigation"> <div class="sidebar-collapse"> <ul class="nav metismenu" id="side-menu"> <li class="nav-header"> <div class="dropdown profile-element"> <img alt="image" class="rounded-circle" src="/img/profile_small.jpg" /> <a data-toggle="dropdown" class="dropdown-toggle" href="#"> <span class="block m-t-xs font-bold">博客园IT</span> <span class="text-muted text-xs block">我是麦兜<b class="caret"></b></span> </a> <ul class="dropdown-menu animated fadeInRight m-t-xs"> <li><a class="dropdown-item" href="profile.html">Profile</a></li> <li><a class="dropdown-item" href="contacts.html">Contacts</a></li> <li><a class="dropdown-item" href="mailbox.html">Mailbox</a></li> <li class="dropdown-divider"></li> <li><a class="dropdown-item" href="login.html">注销</a></li> </ul> </div> <div class="logo-element"> admin </div> </li> <li> <a href="/"><i class="fa fa-th-large"></i> <span class="nav-label">Dashboards</span></a> </li> <li > <a href="javascript:showa(2)"><i class="fa fa-bar-chart-o"></i> <span class="nav-label">客户管理</span><span class="fa arrow"></span></a> <ul class="nav nav-second-level collapse"> <li id="li_2_1"><a href="Customer/Add">添加客户</a></li> <li id="li_2_2"><a href="Customer/List">客户列表</a></li> </ul> </li> <li > <a href="javascript:showa(3)"><i class="fa fa-apple"></i> <span class="nav-label">产品管理</span><span class="fa arrow"></span></a> <ul class="nav nav-second-level collapse"> <li id="li_3_1"><a href="Product/Add">添加产品</a></li> <li id="li_3_2"><a href="Product/List">产品列表</a></li> </ul> </li> </ul> </div> </nav> @Body <div class="footer"> <div> <strong>Copyright</strong> Example Company © 2014-2018 </div> </div> </div> </div> @code{ //页面初始化 protected override void OnInitialized() { //母版页初始化完成后 注册 路由事件 navigationManager.LocationChanged += OnLocationChange; } private void OnLocationChange(object sender,LocationChangedEventArgs e) { string url = e.Location;//获得完整URL //调用全局js 函数 setMenuActive 是客户端js函数名字,后面是参数 jsRuntime.InvokeVoidAsync("setMenuActive",url); } }
@page "/" @namespace BlazorApp3.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>BlazorApp3</title> <base href="~/" /> <link href="/css/bootstrap.min.css" rel="stylesheet"> <link href="/font-awesome/css/font-awesome.css" rel="stylesheet"> <link href="/css/style.css" rel="stylesheet"> <script src="/js/jquery-3.1.1.min.js"></script> <script src="/js/popper.min.js"></script> <script src="/js/bootstrap.js"></script> </head> <body> <app> @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered)) </app> <script src="_framework/blazor.server.js"></script> <script> function showa(i) { console.log(i); $("#side-menu").find("li").removeClass("active"); $(".nav-second-level").removeClass("in"); $("#side-menu").children().eq(i).addClass("active").find("ul").eq(0).addClass("in"); } function setMenuActive(url) { console.log(url); $("#side-menu").find("li").removeClass("active"); $(".nav-second-level").find("li").removeClass("active"); $(".nav-second-level").find("a").each(function () { var childurl = $(this).attr("href"); if (url.indexOf(childurl) > -1) { $(this).parent().addClass("active").parent().parent().addClass("active"); return false; } }); } </script> </body> </html>
点击一级菜单 掉客户都安用showa 函数来实现,这个功能是展开二级菜单(给a表的父标签li添加active样式实现左侧上色,同级元素UL添加in 实现展开),不跳转。
点击二级菜单实现跳转,跳转完成后触发 LocationChanged 事件,事件里面调用js客户端函数 setMenuActive 来实现二级菜单设置active.
c#代码调用Javascript 可以注入IJSRuntime 来实现,这里不详细解释了。
$("#side-menu").find("li").removeClass("active");
$(".nav-second-level").find("li").removeClass("active");
这2行函数事先把之前的样式清空。
$(".nav-second-level").find("a").each(function () {
var childurl = $(this).attr("href");
if (url.indexOf(childurl) > -1)
{
$(this).parent().addClass("active").parent().parent().addClass("active");
return false;
}
});
遍历当前所有一级菜单 如果是当前URL 被选中 就设置active,同时设置二级元素a (就是当前点击 的二级的元素)的父元素为active。
至此,所有功能完成。
如下图。