Enterprise-level component library based on Bootstrap and Blazor

star nuget master download license repo commit

Menu 导航菜单

为页面和功能提供导航的菜单列表。

顶栏

适用广泛的基础用法。

Demo

带图标的顶栏菜单

适用简单的网站应用,通过设置菜单项 MenuItemIcon 属性设置菜单图标

Demo

侧栏

适用于左右结构布局的网站,通过设置 IsVertical 更改导航菜单为侧栏

Demo

带图标的侧栏菜单

通过设置菜单项 MenuItemIcon 属性设置菜单图标

Demo

手风琴效果的侧栏

通过设置 IsAccordion 属性设置手风琴特效侧栏菜单

Demo

带收缩的侧栏效果

通过设置 IsCollapsed 属性设置侧栏菜单为收起状态

Demo

本例中使用布局组件 Layout 来进行网页构建,设置 SideWith="0" 关闭侧边栏宽度设置,使用内部菜单宽度来自适应

我是网站标题
Main

带挂件的菜单

通过设置 MenuItemComponent 属性设置自定义组件到菜单中

Demo

自定义节点收缩

通过设置 MenuItemIsCollapsed 属性设置节点是否收起

Demo

部分菜单禁用功能

通过设置 MenuItemIsDisabled 属性设置节点是否禁用

Demo

本例中 导航二 节点为禁用状态,菜单与其子菜单均不可点击

侧栏的禁用示例

Attributes

Loading...
@page "/menus"

<h3>Menu 导航菜单</h3>

<h4>为页面和功能提供导航的菜单列表。</h4>

<Tips class="mt-3">
    <p><code>Menu</code> 组件一般用法为菜单导航,即点击菜单后地址栏进行重定向导航,但是在实战中有时候不需要导航,通过设置 <code>OnClick</code> 回调委托,自定义处理逻辑,此时通过设置属性 <code>DisableNavigation</code> 即可,本例中由于都是模拟菜单点击并未真正的进行地址栏跳转导航所以所有 <code>Menu</code> 均设置为 <code>true</code> 禁止导航</p>
</Tips>

<Block Title="顶栏" Introduction="适用广泛的基础用法。">
    <Menu Items="@Items" DisableNavigation="true" OnClick="@OnClickMenu" />
    <Logger @ref="Trace" class="mt-3" />
</Block>

<Block Title="带图标的顶栏菜单" Introduction="适用简单的网站应用,通过设置菜单项 <code>MenuItem</code> 的 <code>Icon</code> 属性设置菜单图标">
    <Menu Items="@IconItems" DisableNavigation="true" />
</Block>

<Block Title="侧栏" Introduction="适用于左右结构布局的网站,通过设置 <code>IsVertical</code> 更改导航菜单为侧栏">
    <div style="width:220px;">
        <Menu Items="@SideMenuItems" DisableNavigation="true" IsVertical="true" OnClick="@OnClickSideMenu" style="border-right: 1px solid #e6e6e6;" />
    </div>
    <Logger @ref="TraceSideMenu" class="mt-3" />
</Block>

<Block Title="带图标的侧栏菜单" Introduction="通过设置菜单项 <code>MenuItem</code> 的 <code>Icon</code> 属性设置菜单图标">
    <div style="width:220px;">
        <Menu Items="@IconSideMenuItems" DisableNavigation="true" IsVertical="true" style="border-right: 1px solid #e6e6e6;" />
    </div>
</Block>

<Block Title="手风琴效果的侧栏" Introduction="通过设置 <code>IsAccordion</code> 属性设置手风琴特效侧栏菜单">
    <div style="width:220px;">
        <Menu Items="@IconSideMenuItems" DisableNavigation="true" IsVertical="true" IsAccordion="true" style="border-right: 1px solid #e6e6e6;" />
    </div>
</Block>

<Block Title="带收缩的侧栏效果" Introduction="通过设置 <code>IsCollapsed</code> 属性设置侧栏菜单为收起状态">
    <Alert ShowBar="true">请注意 <code>IsCollapsed</code> 属性仅当 <code>IsVertical</code> 为真时才生效即仅侧边栏菜单时可用</Alert>
    <p>本例中使用布局组件 <code>Layout</code> 来进行网页构建,设置 <code>SideWith="0"</code> 关闭侧边栏宽度设置,使用内部菜单宽度来自适应</p>
    <Layout SideWidth="0" IsFullSide="true" ShowFooter="true">
        <Header>
            <div class="d-flex align-items-center pl-3" style="background-color: #17a2b8; height: 50px; color: #fff;">
                <a style="padding: 4px 12px; color: #fff; background-color: #1ab394; border-color: #1ab394; border-radius: 4px;" class="@ClassString" title="点击展开收缩左侧菜单" @onclick="@CollapseMenu">
                    <i class="fa fa-bars"></i>
                </a>
                <span class="ml-3">我是网站标题</span>
            </div>
        </Header>
        <Side>
            <div class="menu-demo" style="background-color: #2f4050; color: #dcdfe6; height: 100%; padding: 6px 0;">
                <Menu Items="@IconSideMenuItems" IsVertical="true" IsCollapsed="@IsCollapsed" />
            </div>
        </Side>
        <Main>
            <div style="padding: 10rem 1rem;">Main</div>
        </Main>
        <Footer>
            <div class="d-flex justify-content-center align-items-center" style="height: 30px; color: #fff; background-color: #5b6e84;"><a href="https://gitee.com/LongbowEnterprise/BootstrapAdmin" target="_blank" style="color: #fff;">Bootstrap Admin</a></div>
        </Footer>
    </Layout>
</Block>

<Block Title="带挂件的菜单" Introduction="通过设置 <code>MenuItem</code> 的 <code>Component</code> 属性设置自定义组件到菜单中">
    <div style="width:220px;">
        <Menu Items="@WidgetIconSideMenuItems" DisableNavigation="true" IsVertical="true" style="border-right: 1px solid #e6e6e6;" />
    </div>
</Block>

<Block Title="自定义节点收缩" Introduction="通过设置 <code>MenuItem</code> 的 <code>IsCollapsed</code> 属性设置节点是否收起">
    <p>本例中 <b>权限设置</b> 节点为展开状态,其余节点为收起状态</p>
    <div style="width:220px;">
        <Menu Items="@CollapsedIconSideMenuItems" DisableNavigation="true" IsVertical="true" style="border-right: 1px solid #e6e6e6;" />
    </div>
</Block>

<Block Title="部分菜单禁用功能" Introduction="通过设置 <code>MenuItem</code> 的 <code>IsDisabled</code> 属性设置节点是否禁用">
    <p>本例中 <b>导航二</b> 节点为禁用状态,菜单与其子菜单均不可点击</p>
    <Menu Items="@DisabledMenuItems" />
    <p class="mt-3"><b>侧栏的禁用示例</b></p>
    <div style="width:220px;">
        <Menu Items="@DisabledMenuItems" DisableNavigation="true" IsVertical="true" style="border-right: 1px solid #e6e6e6;" />
    </div>
</Block>

<AttributeTable Items="@GetAttributes()" />
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using BootstrapBlazor.Components;
using BootstrapBlazor.Shared.Common;
using BootstrapBlazor.Shared.Pages.Components;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BootstrapBlazor.Shared.Pages
{
    /// <summary>
    /// 
    /// </summary>
    public sealed partial class Menus
    {
        /// <summary>
        /// 
        /// </summary>
        private Logger? Trace { get; set; }

        private Task OnClickMenu(MenuItem item)
        {
            Trace?.Log($"菜单点击项: {item.Text}");
            return Task.CompletedTask;
        }

        /// <summary>
        /// 
        /// </summary>
        private Logger? TraceSideMenu { get; set; }

        private Task OnClickSideMenu(MenuItem item)
        {
            TraceSideMenu?.Log($"菜单点击项: {item.Text}");
            return Task.CompletedTask;
        }

        private bool IsCollapsed { get; set; }

        private string? ClassString => CssBuilder.Default("menu-demo-bar")
            .AddClass("is-collapsed", IsCollapsed)
            .Build();

        private Task CollapseMenu()
        {
            IsCollapsed = !IsCollapsed;
            return Task.CompletedTask;
        }

        private IEnumerable<MenuItem> Items { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "导航一" },
                new MenuItem() { Text = "导航二", IsActive = true },
                new MenuItem() { Text = "导航三" }
            };

            ret[1].AddItem(new MenuItem() { Text = "子菜单一" });
            ret[1].AddItem(new MenuItem() { Text = "子菜单二" });
            ret[1].AddItem(new MenuItem() { Text = "子菜单三" });

            ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1一" });
            ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1二" });

            ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2一" });
            ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2二" });

            ret[1].Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾孙菜单一" });
            ret[1].Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾孙菜单二" });

            ret[1].Items.ElementAt(1).Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾曾孙菜单一" });
            ret[1].Items.ElementAt(1).Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾曾孙菜单二" });

            return ret;
        }

        private IEnumerable<MenuItem> IconItems { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetIconItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "导航一", Icon = "fa fa-life-bouy fa-fw" },
                new MenuItem() { Text = "导航二", Icon = "fa fa-fa fa-fw", IsActive = true },
                new MenuItem() { Text = "导航三", Icon = "fa fa-rebel fa-fw" }
            };

            ret[1].AddItem(new MenuItem() { Text = "子菜单一", Icon = "fa fa-fa fa-fw" });
            ret[1].AddItem(new MenuItem() { Text = "子菜单二", Icon = "fa fa-fa fa-fw" });
            ret[1].AddItem(new MenuItem() { Text = "子菜单三", Icon = "fa fa-fa fa-fw" });

            return ret;
        }

        private IEnumerable<MenuItem> SideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetSideMenuItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "导航一" },
                new MenuItem() { Text = "导航二" },
                new MenuItem() { Text = "导航三" },
                new MenuItem() { Text = "导航四" }
            };

            ret[1].AddItem(new MenuItem() { Text = "子菜单一" });
            ret[1].AddItem(new MenuItem() { Text = "子菜单二" });
            ret[1].AddItem(new MenuItem() { Text = "子菜单三" });

            ret[3].AddItem(new MenuItem() { Text = "子菜单一" });
            ret[3].AddItem(new MenuItem() { Text = "子菜单二" });
            ret[3].AddItem(new MenuItem() { Text = "子菜单三" });

            ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1一" });
            ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1二" });

            ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2一" });
            ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2二" });

            ret[1].Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾孙菜单一" });
            ret[1].Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾孙菜单二" });

            ret[1].Items.ElementAt(0).Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾曾孙菜单一" });
            ret[1].Items.ElementAt(0).Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾曾孙菜单二" });

            return ret;
        }

        private IEnumerable<MenuItem> IconSideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetIconSideMenuItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "系统设置", IsActive = true, Icon = "fa fa-fw fa-gears" },
                new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
                new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
            };

            ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
            ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });

            ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
            ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
            ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });

            ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
            ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
            ret[2].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });

            return ret;
        }

        private DynamicComponent BuildDynamicComponent()
        {
            return DynamicComponent.CreateComponent<Badge>(new KeyValuePair<string, object>[]
            {
                new KeyValuePair<string, object>(nameof(Badge.Color), Color.Danger),
                new KeyValuePair<string, object>(nameof(Badge.IsPill), true),
                new KeyValuePair<string, object>(nameof(Badge.ChildContent), new RenderFragment(builder =>
                {
                    var index = 0;
                    builder.AddContent(index++, "10");
                }))
            });
        }

        private IEnumerable<MenuItem> WidgetIconSideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetWidgetIconSideMenuItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "系统设置", Icon = "fa fa-fw fa-gears" },
                new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
                new MenuItem() {
                    Text = "日志设置",
                    IsActive = true,
                    Icon = "fa fa-fw fa-database",
                    Component = BuildDynamicComponent()
                }
            };

            ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
            ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });

            ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
            ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
            ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });

            ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
            ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
            ret[2].AddItem(new MenuItem()
            {
                Text = "操作日志",
                Icon = "fa fa-fw fa-edit",
                Component = BuildDynamicComponent()
            });

            return ret;
        }

        private IEnumerable<MenuItem> CollapsedIconSideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetCollapsedIconSideMenuItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "系统设置", Icon = "fa fa-fw fa-gears" },
                new MenuItem() { Text = "权限设置", IsActive = true, Icon = "fa fa-fw fa-users" , IsCollapsed = false },
                new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
            };

            ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
            ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });

            ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
            ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
            ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });

            ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
            ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
            ret[2].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });

            return ret;
        }

        private IEnumerable<MenuItem> DisabledMenuItems { get; set; } = Enumerable.Empty<MenuItem>();

        private IEnumerable<MenuItem> GetDisabledMenuItems()
        {
            var ret = new List<MenuItem>
            {
                new MenuItem() { Text = "导航一", IsActive = true },
                new MenuItem() { Text = "导航二", IsDisabled = true },
                new MenuItem() { Text = "导航三" },
                new MenuItem() { Text = "导航四", IsDisabled = true },
            };

            ret[1].AddItem(new MenuItem() { Text = "子菜单一", Icon = "fa fa-fa fa-fw" });

            ret[2].AddItem(new MenuItem() { Text = "子菜单二", Icon = "fa fa-fa fa-fw" });
            ret[2].AddItem(new MenuItem() { Text = "子菜单三", Icon = "fa fa-fa fa-fw", IsDisabled = true });

            return ret;
        }

        /// <summary>
        /// OnInitialized 方法
        /// </summary>
        protected override void OnInitialized()
        {
            base.OnInitialized();
            Items = GetItems();
            IconItems = GetIconItems();
            SideMenuItems = GetSideMenuItems();
            IconSideMenuItems = GetIconSideMenuItems();
            WidgetIconSideMenuItems = GetWidgetIconSideMenuItems();
            CollapsedIconSideMenuItems = GetCollapsedIconSideMenuItems();
            DisabledMenuItems = GetDisabledMenuItems();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private IEnumerable<AttributeItem> GetAttributes()
        {
            return new AttributeItem[]
            {
                new AttributeItem()
                {
                    Name = "Items",
                    Description = "菜单组件数据集合",
                    Type = "IEnumerable<MenuItem>",
                    ValueList = " — ",
                    DefaultValue = " — "
                },
                new AttributeItem()
                {
                    Name = "IsVertical",
                    Description = "是否为侧栏",
                    Type = "bool",
                    ValueList = "true|false",
                    DefaultValue = "false"
                },
                new AttributeItem() {
                    Name = "IsAccordion",
                    Description = "是否手风琴效果",
                    Type = "bool",
                    ValueList = "true|false",
                    DefaultValue = "false"
                },
                new AttributeItem() {
                    Name = "DisableNavigation",
                    Description = "是否禁止地址栏导航",
                    Type = "bool",
                    ValueList = "true|false",
                    DefaultValue = "false"
                },
                new AttributeItem() {
                    Name = "OnClick",
                    Description = "菜单项被点击时回调此方法",
                    Type = "Func<MenuItem, Task>",
                    ValueList = " — ",
                    DefaultValue = " — "
                }
            };
        }
    }
}

B 站相关视频链接

暂无

交流群

QQ群: BootstrapAdmin & Blazor(795206915)欢迎加群讨论
An error has occurred. This application may no longer respond until reloaded. Reload