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>
 
但是 NavLink 只能实现自身 加active 样式,且只能是a标签 ,实际项目中可能a 标签父元素 需要设置 active 样式或者更外层的元素。例如本模板

当前点击菜单父层 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 &copy; 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。

至此,所有功能完成。

如下图。

01-07 10:02