SxAppShell (应用外壳)

  • Implemented

提供响应式应用基础布局,包含侧边栏、顶部导航栏和主内容区域。支持自动响应式切换、内部导航、多 Tab 历史栈等高级功能。

使用场景

  • 应用级响应式布局(桌面/移动端自适应)
  • 侧边栏 + 顶部导航栏布局
  • 单页应用(SPA)内部导航
  • 多 Tab 页面缓存与历史管理

基本用法

最简单的用法

<SxAppRoot>
    <SxAppShell TitleText="我的应用">
        <Navigation>
            <SxNavMenu>
                <SxNavMenuLink Text="首页" IconName="house" Href="/" />
                <SxNavMenuLink Text="设置" IconName="gear" Href="/settings" />
            </SxNavMenu>
        </Navigation>
        <Content>
            @(context => @<div>主内容区域</div>)
        </Content>
    </SxAppShell>
</SxAppRoot>

完整示例

<SxAppRoot>
    <SxAppShell TitleText="企业管理系统"
                ShowCollapseToggle="true"
                @bind-Collapsed="_collapsed"
                SizingMode="SxAppShellSizingMode.Viewport"
                BreakpointChanged="OnBreakpointChanged">
        <Navigation>
            @RenderNavigation
        </Navigation>
        <Content>
            @(isWide => @<div class="@(isWide ? "wide-layout" : "narrow-layout")">
                @Body
            </div>)
        </Content>
    </SxAppShell>
</SxAppRoot>

@code {
    private bool _collapsed;

    private RenderFragment RenderNavigation => __builder =>
    {
        <SxNavMenu>
            <SxNavMenuGroup Text="用户管理" IconName="users">
                <SxNavMenuLink Text="用户列表" Href="/users" />
                <SxNavMenuLink Text="角色管理" Href="/roles" />
            </SxNavMenuGroup>
            <SxNavMenuLink Text="系统设置" IconName="gear" Href="/settings" />
        </SxNavMenu>
    };

    private void OnBreakpointChanged(SxAppShell.Breakpoint breakpoint)
    {
        Console.WriteLine($"断点变化: {breakpoint}");
    }
}

布局模式

SxAppShell 支持三种布局模式,通过 LayoutMode 参数控制:

自动模式(默认)

<SxAppShell LayoutMode="null">
    <!-- 宽屏(LG/XL)使用侧边栏,窄屏(XS/SM/MD)使用抽屉 -->
</SxAppShell>
  • 宽屏(≥LG):固定侧边栏 + 可拖拽分割条
  • 窄屏(<LG):抽屉式导航 + 汉堡菜单按钮

强制侧边栏模式

<SxAppShell LayoutMode="SxAppShellLayoutMode.Sidebar">
    <!-- 始终使用侧边栏布局,即使在移动端 -->
</SxAppShell>

强制抽屉模式

<SxAppShell LayoutMode="SxAppShellLayoutMode.Drawer">
    <!-- 始终使用抽屉布局,侧边显示窄条(Rail) -->
</SxAppShell>

响应式断点

默认断点

断点 宽度 布局行为
XS < 576px 抽屉模式,侧边栏完全隐藏
SM ≥ 576px 抽屉模式,侧边栏完全隐藏
MD ≥ 768px 抽屉模式,显示窄条(Rail)
LG ≥ 992px 侧边栏模式
XL ≥ 1200px 侧边栏模式

自定义断点

<SxAppShell BreakpointConfig="@_breakpointConfig">
    ...
</SxAppShell>

@code {
    private SxAppShellBreakpointConfig _breakpointConfig = new()
    {
        XS = "0px",
        SM = "480px",
        MD = "768px",
        LG = "1024px",
        XL = "1280px"
    };
}

容器尺寸模式

默认情况下,断点基于视口(Viewport)宽度计算。如果 SxAppShell 嵌入在容器中,可以使用容器尺寸:

<div style="width: 800px; height: 600px;">
    <SxAppShell SizingMode="SxAppShellSizingMode.Container">
        <!-- 断点基于容器宽度而非视口宽度 -->
    </SxAppShell>
</div>

侧边栏折叠

基本折叠控制

<SxAppShell @bind-Collapsed="_collapsed"
            ShowCollapseToggle="true">
    ...
</SxAppShell>

@code {
    private bool _collapsed;

    private void ExpandSidebar() => _collapsed = false;
    private void CollapseSidebar() => _collapsed = true;
}

折叠宽度

<SxAppShell Collapsed="true"
            CollapsedWidth="60px">
    <!-- 折叠时侧边栏宽度为 60px -->
</SxAppShell>

窄条(Rail)显示控制

<!-- 自动:MD 及以上显示窄条,SM/XS 隐藏 -->
<SxAppShell CollapsedRailMode="SxAppShellCollapsedRailMode.Auto" />

<!-- 始终显示窄条 -->
<SxAppShell CollapsedRailMode="SxAppShellCollapsedRailMode.Show" />

<!-- 始终隐藏窄条 -->
<SxAppShell CollapsedRailMode="SxAppShellCollapsedRailMode.Hidden" />

始终显示侧边栏

在小屏幕上也保持显示折叠的侧边栏(窄条):

<SxAppShell AlwaysShowSidebar="true">
    <!-- 即使在 XS/SM 断点也显示窄条 -->
</SxAppShell>

折叠时显示内容区导航栏

<!-- 默认行为:折叠时在内容区顶部显示导航栏 -->
<SxAppShell Collapsed="true" ShowContentNavBarWhenCollapsed="true" />

<!-- 禁用:折叠时不显示内容区导航栏 -->
<SxAppShell Collapsed="true" ShowContentNavBarWhenCollapsed="false" />

抽屉遮罩

控制抽屉展开时的遮罩层行为:

<!-- 透明遮罩,点击可关闭抽屉 -->
<SxAppShell DrawerOverlayMode="SxAppShellDrawerOverlayMode.Transparent" />

<!-- 隐藏遮罩,抽屉不遮挡内容区 -->
<SxAppShell DrawerOverlayMode="SxAppShellDrawerOverlayMode.Hidden" />

自定义导航栏

NavBarTemplate 参数接收一个布尔值,表示当前是否为侧边栏模式:

<SxAppShell>
    <NavBarTemplate>
        @{ var isSidebarMode = context; }
        <SxNavBar TitleText="我的应用"
                  IsSidebarMode="@isSidebarMode"
                  ShowHamburger="@isSidebarMode">
            <LeftActions>
                @if (!isSidebarMode)
                {
                    <SxButton Appearance="ButtonAppearance.Stealth"
                              IconStart="bars"
                              OnClick="ToggleSidebar" />
                }
            </LeftActions>
            <FunctionalMenu>
                <SxMenuItem Text="设置" Icon="gear" />
                <SxMenuItem Text="退出" Icon="sign-out" />
            </FunctionalMenu>
        </SxNavBar>
    </NavBarTemplate>
    <Navigation>
        <SxNavMenu>...</SxNavMenu>
    </Navigation>
</SxAppShell>

自定义导航菜单

<SxAppShell>
    <Navigation>
        <SxNavMenu>
            <!-- 普通链接 -->
            <SxNavMenuLink Text="首页" IconName="house" Href="/" />

            <!-- 分组 -->
            <SxNavMenuGroup Text="用户管理" IconName="users" DefaultOpen="true">
                <SxNavMenuLink Text="用户列表" Href="/users" />
                <SxNavMenuLink Text="角色管理" Href="/roles" />
                <SxNavMenuLink Text="权限设置" Href="/permissions" />
            </SxNavMenuGroup>

            <!-- 带徽标 -->
            <SxNavMenuLink Text="消息" IconName="envelope" Href="/messages">
                <Badge>
                    <SxBadge>5</SxBadge>
                </Badge>
            </SxNavMenuLink>

            <!-- 分隔线 -->
            <SxNavMenuDivider />

            <!-- 外部链接 -->
            <SxNavMenuLink Text="帮助文档"
                           IconName="question-circle"
                           Href="https://docs.example.com"
                           Target="_blank" />
        </SxNavMenu>
    </Navigation>
</SxAppShell>

底部栏 (BottomBar)

SxAppShell 提供了一个 BottomBar RenderFragment 插槽,用于在侧边栏底部放置固定内容。这是一个通用容器,可以放置任意组件,最常见的用途是放置 SxUserBar 用户栏组件。

设计理念

  • 容器与内容分离:BottomBar 只是一个容器,不包含业务逻辑
  • 固定定位:BottomBar 固定在侧边栏底部,不随导航内容滚动
  • 毛玻璃效果:内置半透明背景和模糊效果,滚动内容从其下方穿过
  • 灵活组合:可放置 SxUserBar、自定义按钮或任何其他组件

基本用法

<SxAppShell>
    <Navigation>
        <SxNavMenu>
            <SxNavMenuLink Text="首页" IconName="house" Href="/" />
            <SxNavMenuLink Text="设置" IconName="gear" Href="/settings" />
        </SxNavMenu>
    </Navigation>
    <BottomBar>
        <SxUserBar UserName="张三"
                   UserSubtitle="admin@example.com"
                   UserPresence="AvatarPresence.Online"
                   OnLogout="HandleLogout"
                   OnSettings="HandleSettings" />
    </BottomBar>
</SxAppShell>

@code {
    private async Task HandleLogout()
    {
        await AuthService.LogoutAsync();
        NavigationManager.NavigateTo("/login");
    }

    private void HandleSettings()
    {
        NavigationManager.NavigateTo("/settings");
    }
}

SxUserBar 配置

SxUserBar 是一个独立组件,自动响应 SxAppShell 的折叠状态:

<SxAppShell @bind-Collapsed="_collapsed">
    <Navigation>...</Navigation>
    <BottomBar>
        <SxUserBar UserName="张三"
                   UserSubtitle="admin@example.com"
                   UserAvatarUrl="/avatars/user.jpg"
                   ShowSettings="true"
                   ShowQuickSettings="true"
                   ShowLogout="true"
                   OnLogout="HandleLogout"
                   OnSettings="HandleSettings"
                   OnUserClick="HandleUserClick">
            <MenuContent>
                <!-- 自定义菜单项(显示在内置项之前) -->
                <SxMenuItem Text="我的订单" Icon="shopping-cart" OnClick="..." />
                <SxMenuItem Text="消息中心" Icon="bell" OnClick="..." />
                <SxMenuDivider />
            </MenuContent>
        </SxUserBar>
    </BottomBar>
</SxAppShell>

SxUserBar 参数

参数 类型 默认值 说明
UserName string? "User" 用户名
UserSubtitle string? null 副标题(邮箱/角色)
UserAvatarUrl string? null 头像 URL
UserPresence AvatarPresence None 在线状态(默认不显示)
MenuContent RenderFragment? null 自定义菜单项
ShowSettings bool true 显示设置菜单项
ShowQuickSettings bool true 显示快捷设置(主题/语言)
ShowLogout bool true 显示退出登录菜单项
OnLogout EventCallback 退出登录点击事件
OnSettings EventCallback 设置点击事件
OnUserClick EventCallback 用户信息区域点击事件

交互行为

SxUserBar 分为两个独立的可点击区域:

  • 用户信息区域(头像 + 用户名):点击触发 OnUserClick 事件,可用于跳转到用户资料页
  • 箭头按钮:点击弹出菜单,箭头图标会旋转指示菜单状态
<SxUserBar UserName="张三"
           OnUserClick="@(() => Nav.NavigateTo("/profile"))"
           OnLogout="HandleLogout"
           OnSettings="HandleSettings" />

折叠状态适配

SxUserBar 通过 CascadingParameter 接收 SxAppShellContext,自动响应折叠状态:

  • 展开状态:显示头像、用户名、副标题和箭头按钮
  • 折叠状态:仅显示头像,点击头像弹出菜单

自定义底部栏内容

BottomBar 可以放置任意内容,不限于 SxUserBar:

<SxAppShell>
    <Navigation>...</Navigation>
    <BottomBar>
        <!-- 自定义底部栏:版本信息 -->
        <div style="padding: var(--sx-spacing-m) var(--sx-shell-rail-pad-x); text-align: center;">
            <SxTypography Variant="TypographyVariant.Caption">v1.0.0</SxTypography>
        </div>
    </BottomBar>
</SxAppShell>

毛玻璃效果

BottomBar 容器自带毛玻璃效果(backdrop-filter),当导航菜单滚动时,内容会从底部栏下方透过:

.sx-sidebar-bottom-bar {
    background: color-mix(in srgb, var(--sx-colorNeutralBackground2) 80%, transparent);
    backdrop-filter: blur(12px);
}

内部导航

SxAppShell 支持内部导航模式,页面切换在外壳内部完成,不触发浏览器导航。

<SxAppShell NavigationMode="SxAppShellNavigationMode.Internal"
            InitialRoute="/dashboard"
            OnNavigate="HandleNavigate">
    <Navigation>
        <SxNavMenu>
            <SxNavMenuLink Text="仪表盘" IconName="chart-line" Href="/dashboard" />
            <SxNavMenuLink Text="用户" IconName="users" Href="/users" />
        </SxNavMenu>
    </Navigation>
    <NavigationContent>
        @{ var route = context; }
        @switch (route)
        {
            case "/dashboard":
                <DashboardPage />
                break;
            case "/users":
                <UsersPage />
                break;
            default:
                <NotFoundPage />
                break;
        }
    </NavigationContent>
</SxAppShell>

@code {
    private void HandleNavigate(string? route)
    {
        Console.WriteLine($"导航到: {route}");
    }
}

基于路由程序集

<SxAppShell NavigationMode="SxAppShellNavigationMode.Auto"
            RouteAppAssembly="@typeof(Program).Assembly"
            InitialRoute="/dashboard">
    <Navigation>
        <SxNavMenu>
            <SxNavMenuLink Text="仪表盘" Href="/dashboard" />
            <SxNavMenuLink Text="用户" Href="/users" />
        </SxNavMenu>
    </Navigation>
</SxAppShell>

浏览器 URL 同步

<!-- 默认:同步浏览器 URL -->
<SxAppShell SyncBrowserUrl="true" />

<!-- 禁用同步(适用于嵌套或演示场景) -->
<SxAppShell SyncBrowserUrl="false" />

历史栈限制

<SxAppShell MaxHistoryDepth="10"
            MaxCachedPages="20">
    <!-- 每个 Tab 最多保留 10 条历史记录 -->
    <!-- 全局最多缓存 20 个页面 -->
</SxAppShell>

两种导航模式对比

SxAppShell 提供两种主要的内容渲染方式:

特性 Content + @Body RouteAppAssembly
路由处理 由外层 Blazor <Router> 处理 SxAppShell 内部接管
页面生命周期 切换时销毁旧页面、创建新页面 页面保留在 DOM 中(display:none
状态保持 不支持 支持(表单值、滚动位置等完整保留)
历史栈 每个导航节点独立维护
需要 LayoutComponentBase
需要外层 Router
适用场景 简单应用,或已有 Blazor Router 体系 复杂应用、MAUI Hybrid、需要状态保持

Content + @Body 模式

传统模式,MainLayout 继承 LayoutComponentBase,由 Blazor Router 做路由匹配并通过 @Body 渲染:

@inherits LayoutComponentBase

<SxAppShell>
    <Content>
        <div class="my-content">@Body</div>
    </Content>
</SxAppShell>

每次侧边栏切换都会销毁旧页面组件、创建新组件,页面状态(如表单输入、滚动位置)会丢失。

RouteAppAssembly 模式

SxAppShell 接管路由渲染,内部使用 SxRouteView 做路由匹配和页面管理:

<SxAppShell RouteAppAssembly="@typeof(Routes).Assembly"
            RouteFound="@RenderRouteContent"
            RouteNotFound="@RenderNotFound"
            InitialRoute="/">
    <Navigation>...</Navigation>
</SxAppShell>

@code {
    private RenderFragment<RouteData> RenderRouteContent => routeData => __builder =>
    {
        <div class="my-content">
            <RouteView RouteData="@routeData" />
        </div>
    };

    private RenderFragment RenderNotFound => __builder =>
    {
        <SxTypography Variant="TypographyVariant.H3">Page Not Found</SxTypography>
    };
}

页面状态保持原理

启用 RouteAppAssembly 后,页面切换行为如下:

  1. 首次访问:创建页面组件实例,渲染到 DOM
  2. 离开页面:组件实例和 DOM 保留,通过 display:none 隐藏
  3. 再次访问:直接显示缓存的页面,不重新创建组件
  4. 堆栈管理:每个侧边栏导航节点对应独立的 Tab 堆栈,深入子页面后返回时状态完整保留

侧边栏节点间的状态保持:在不同导航节点之间切换时,每个节点的页面状态互不影响、各自保留。具体来说:

  • 页面组件不销毁:从「设备信息」切到「诊断中心」时,「设备信息」的组件实例仍然存活,只是所在 DOM 被设置为 display:none
  • 表单值、滚动位置、组件内部状态全部保留:切回时页面恢复到离开时的状态
  • 子页面堆栈独立:在「设备信息」中深入到子页面后切换到其他节点,再切回时子页面堆栈完整保留

这是 RouteAppAssembly 模式与 Content+@Body 模式的核心区别——后者每次侧边栏切换都会销毁旧页面组件、创建新组件,所有临时状态丢失。

缓存限制与超限行为

默认情况下,所有导航节点和历史记录不设限制,全部保留在内存中。通过以下参数控制资源占用:

参数 类型 默认值 作用域
MaxHistoryDepth int? null(无限制) 单个 Tab 堆栈
MaxCachedPages int? null(无限制) 全局(跨所有 Tab)

MaxHistoryDepth — 限制单个 Tab 内的历史深度。当某个 Tab 的历史条目数超过此值时,最早的条目(栈底)被移除,对应页面组件销毁。下次导航到该路由时页面将重新创建(状态丢失)。

MaxCachedPages — 限制所有 Tab 缓存的页面总数。超限时按 LRU(最近最少使用)策略淘汰:

  1. 收集所有 Tab 中的全部页面条目,按最后活跃时间排序
  2. 从最久未访问的条目开始淘汰,当前各 Tab 的活跃页面不会被淘汰
  3. 被淘汰的页面组件销毁,下次导航到时重新渲染

导航节点(Tab)数量没有上限参数,侧边栏有多少个菜单项就会创建多少个 Tab。限制的是每个 Tab 内部的历史深度和全局的缓存页面总数。

<!-- 推荐:页面较多的应用设置合理限制 -->
<SxAppShell MaxHistoryDepth="10"
            MaxCachedPages="20"
            RouteAppAssembly="@typeof(Routes).Assembly">
    ...
</SxAppShell>

注意事项

  1. 不要同时使用两种模式:设置了 RouteAppAssembly 后,不要同时设置 Content 参数,否则 Content 会被忽略
  2. 不需要外层 RouterRouteAppAssembly 模式下,SxAppShell 内部已包含路由匹配逻辑,不需要在外层用 <Router> 包裹
  3. TabKey 自定义分组:每个侧边栏节点自动对应一个独立 Tab 堆栈。如需自定义分组,可通过 SxNavMenuLinkTabKey 属性指定
  4. InitialRoute 建议设置:不提供 InitialRoute 时首次加载可能显示空白,建议始终指定默认路由
  5. RouteFound 可选:如果不提供 RouteFound,SxAppShell 使用默认的 <RouteView> 渲染。自定义 RouteFound 可以包裹额外的布局容器

从 Content 迁移到 RouteAppAssembly

步骤 1:修改 MainLayout

- @inherits LayoutComponentBase

  <SxAppShell Navigation="@RenderNav"
-             ...>
-     <Content>
-         <div class="my-content">@Body</div>
-     </Content>
+             InitialRoute="/"
+             RouteAppAssembly="@typeof(Routes).Assembly"
+             RouteFound="@RenderRouteContent"
+             RouteNotFound="@RenderNotFound"
+             ...>
  </SxAppShell>

+ @code {
+     private RenderFragment<RouteData> RenderRouteContent => routeData => __builder =>
+     {
+         <div class="my-content">
+             <RouteView RouteData="@routeData" />
+         </div>
+     };
+
+     private RenderFragment RenderNotFound => __builder =>
+     {
+         <SxTypography Variant="TypographyVariant.H3">Page Not Found</SxTypography>
+     };
+ }

步骤 2:简化 Routes.razor

- <Router AppAssembly="typeof(Routes).Assembly">
-     <Found Context="routeData">
-         <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
-     </Found>
-     <NotFound>
-         <LayoutView Layout="typeof(MainLayout)">
-             <p>Page not found.</p>
-         </LayoutView>
-     </NotFound>
- </Router>
+ <MainLayout />

步骤 3:验证

  • 编译通过
  • 侧边栏导航切换后页面状态保持
  • 浏览器 URL 跟随导航同步更新
  • 深入子页面后返回时状态完整保留

Blazor Server 预渲染

ServerPrerendered 模式

在使用 render-mode="ServerPrerendered" 时,必须为 SxAppShell 提供稳定的 Id 参数,以确保服务端预渲染和客户端水合使用相同的 ID:

<!-- _Layout.cshtml -->
<body>
    <component type="typeof(AppShell)" render-mode="ServerPrerendered" />
    <script src="/_framework/blazor.server.js"></script>
</body>
<!-- AppShell.razor -->
<SxAppRoot>
    <SxAppShell Id="main-shell"
                ShowCollapseToggle="true"
                @bind-Collapsed="_collapsed"
                TitleText="我的应用">
        <Navigation>
            <SxNavMenu>
                <SxNavMenuLink Text="首页" IconName="house" Href="/" />
            </SxNavMenu>
        </Navigation>
        <Content>
            @(isWide => @<main id="content-slot"></main>)
        </Content>
    </SxAppShell>
</SxAppRoot>

@code {
    private bool _collapsed;
}

注意事项

  1. 必须提供 Id 参数:避免预渲染和水合时 ID 不一致导致事件处理器失效
  2. 确保服务注册IUserPreferencesINavStackService 等服务必须在 DI 容器中注册
  3. 避免依赖 JS 初始状态:断点检测等 JS 功能在预渲染时不可用,组件会在水合后初始化

不同渲染模式对比

渲染模式 描述 注意事项
ServerPrerendered HTML 预渲染 + SignalR 交互 需要稳定 Id
Server 仅 SignalR 交互 无预渲染闪烁,首屏稍慢
WebAssembly 客户端渲染 无特殊注意事项
WebAssemblyPrerendered HTML 预渲染 + WASM 交互 需要稳定 Id

嵌套 Shell

SxAppShell 支持嵌套使用(如演示场景)。嵌套的 Shell 会自动禁用浏览器 URL 同步:

<SxAppShell Id="outer-shell">
    <Content>
        @(isWide => @<div class="demo-container">
            <!-- 嵌套的 Shell,不会影响浏览器 URL -->
            <SxAppShell Id="inner-shell"
                        SyncBrowserUrl="false"
                        SizingMode="SxAppShellSizingMode.Container">
                ...
            </SxAppShell>
        </div>)
    </Content>
</SxAppShell>

API

Parameters

参数名 类型 默认值 描述
Id string? null 组件 ID,ServerPrerendered 模式必须提供
Navigation RenderFragment? null 侧边栏导航内容
NavBarTemplate RenderFragment<bool>? null 导航栏模板(参数为是否侧边栏模式)
Content RenderFragment<bool>? null 主内容模板(参数为是否宽屏)
TitleText string? null 默认导航栏标题文本
ShowCollapseToggle bool true 是否显示内置折叠切换按钮
Collapsed bool false 侧边栏折叠状态
CollapsedWidth string? null 折叠宽度(如 "60px"
CollapsedRailMode SxAppShellCollapsedRailMode Auto 窄条显示策略
AlwaysShowSidebar bool? null 是否始终显示侧边栏(小屏幕也显示窄条)
ShowContentNavBarWhenCollapsed bool true 折叠时是否显示内容区导航栏
SizingMode SxAppShellSizingMode Viewport 尺寸策略(Viewport/Container
LayoutMode SxAppShellLayoutMode? null 布局模式(null=自动, Sidebar, Drawer
BreakpointConfig SxAppShellBreakpointConfig? null 自定义断点配置
DrawerOverlayMode SxAppShellDrawerOverlayMode Transparent 抽屉遮罩模式
EnableSafeArea bool true 是否启用安全区(移动端)
NavigationMode SxAppShellNavigationMode Auto 导航模式
NavigationContent RenderFragment<string?>? null 内部导航内容模板
RouteAppAssembly Assembly? null 内部路由程序集
RouteAdditionalAssemblies IEnumerable<Assembly>? null 额外路由程序集
RouteDefaultLayout Type? null 默认布局类型
RouteFound RenderFragment<RouteData>? null 路由匹配模板
RouteNotFound RenderFragment? null 路由未匹配模板
InitialRoute string? null 初始路由路径
SyncBrowserUrl bool true 是否同步浏览器 URL
MaxHistoryDepth int? null 单 Tab 历史栈深度限制
MaxCachedPages int? null 缓存页面数量限制
BottomBar RenderFragment? null 底部栏内容(固定在侧边栏底部,可放置 SxUserBar 等组件)

Events

事件名 类型 描述
BreakpointChanged EventCallback<Breakpoint> 断点变化时触发
CollapsedChanged EventCallback<bool> 折叠状态变化时触发
OnNavigate EventCallback<string?> 内部导航时触发
OnBack EventCallback 返回时触发
OnHome EventCallback 返回首页时触发

Methods

方法名 返回值 描述
ToggleSidebar() void 切换侧边栏折叠状态
OnBreakpointChanged(string) void JS 调用的断点变化回调

枚举类型

public enum Breakpoint { XS, SM, MD, LG, XL }

public enum SxAppShellSizingMode { Viewport, Container }

public enum SxAppShellLayoutMode { Auto, Sidebar, Drawer }

public enum SxAppShellCollapsedRailMode { Auto, Show, Hidden }

public enum SxAppShellDrawerOverlayMode { Transparent, Hidden }

public enum SxAppShellNavigationMode { Auto, Internal, External }

常见问题

Q: 点击折叠按钮无响应?

检查以下几点:

  1. ServerPrerendered 模式下是否提供了 Id 参数
  2. IUserPreferencesINavStackService 服务是否已注册
  3. 浏览器控制台是否有 JS 错误

Q: 断点变化不触发?

确保:

  1. blazor.server.jsblazor.webassembly.js 已正确加载
  2. 组件已完成水合(预渲染模式)
  3. BreakpointConfig 配置正确

Q: 内部导航不工作?

检查:

  1. NavigationMode 是否正确设置
  2. NavigationContentRouteAppAssembly 是否提供
  3. SyncBrowserUrl 设置是否符合预期

参考设计