Ant Design Blazor Collapse 手风琴模式实战指南:Accordion 单面板展开原理与配置详解

  • 前端
  • UI组件
  • 设计系统

【免费下载链接】ant-design-blazor

基于 Ant Design 与 Blazor 的前端组件库。让开发者解放生产力,实现更大价值。

项目地址: https://gitcode.com/ant-design-blazor/ant-design-blazor
点击查看 免费下载

在 Ant Design Blazor 组件库中,Collapse(折叠面板)默认允许同时展开多个面板,而开启 Accordion 属性后,组件会切换为手风琴模式:同一时刻只允许一个面板处于展开状态,展开新面板时其余面板自动收起。本文以官方演示文档 accordion.md 为核心,结合组件源码与完整 API,讲解手风琴模式的用法、底层实现原理及周边配置,帮助你在 Blazor 项目中准确、高效地落地这一交互模式。

一、手风琴模式是什么

手风琴(Accordion)是折叠面板的一种特殊形态。官方文档 index.zh-CN.md 中明确指出其适用场景:

  • 对复杂区域进行分组和隐藏,保持页面的整洁;
  • 手风琴是一种特殊的折叠面板,只允许单个内容区域展开。

与之相对,普通模式下可以同时展开多个面板(参见 Basic.md 的演示:"可以同时展开多个面板")。手风琴模式的核心特征是互斥展开:用户点击某个面板的标题时,其他已展开的面板会被强制收起,保证页面任意时刻只有一个内容区可见。

二、手风琴模式的最小可运行示例

在 Collapse 组件上设置 Accordion 属性(布尔值)即可开启手风琴模式。官方演示 Accordion.razor 给出了完整的最小示例:

<Collapse DefaultActiveKey="@(new[]{"1"})" Accordion>
    <Panel Header="This is panel header 1" Key="1">
        <p>@text</p>
    </Panel>
    <Panel Header="This is panel header 2" Key="2">
        <p>@text</p>
    </Panel>
    <Panel Header="This is panel header 3" Key="3">
        <p>@text</p>
    </Panel>
</Collapse>

@code{

    string text = @"
A dog is a type of domesticated animal.
Known for its loyalty and faithfulness,
it can be found as a welcome guest in many households across the world.
";

}

几个关键点:

  • Accordion 为 boolean 类型,默认值 false,设置为 true 即进入手风琴模式;
  • DefaultActiveKey 接收 string[] 类型的 key 数组,用于设置初始化时展开的面板。示例中传入 new[]{"1"},因此页面加载时第一个面板(Key="1")处于展开状态;
  • Panel 的 Key 是每个面板的唯一标识,手风琴模式下互斥判断正是基于这些 key 展开的;
  • 面板内容(<p>@text</p>)可自由替换为任意 Blazor 内容片段。

三、Collapse 与 Panel 的完整 API

为了让手风琴模式的使用更灵活,需要掌握 Collapse 与 Panel 的全部参数。以下参数表摘自 index.zh-CN.md,并结合源码 Collapse.razor.cs 与 Panel.razor.cs 补充了默认值与类型细节。

Collapse 参数

参数说明类型默认值
Accordion是否每次只打开一个 tabbooleanfalse
Bordered是否有边框booleantrue
ExpandIconPosition设置图标位置'left' \| 'right'left
Animation是否开启动画booleanfalse
DefaultActiveKey默认展开的 Panel 的 Key 数组string[]Array.Empty<string>()
ActiveKeys当前展开的 Panel 的 Key 数组,支持双向绑定string[]-
ActiveKeysChangedActiveKeys 的双向绑定回调EventCallback<string[]>-
OnChange展开面板发生变化时的回调EventCallback<string[]>-
ExpandIcon展开图标类型stringIconType.Outline.Right
ExpandIconTemplate自定义展开图标内容(优先于 ExpandIcon)RenderFragment<bool>-

Panel 参数

参数说明类型默认值
Disabled禁用后的面板展开与否将无法通过用户交互改变booleanfalse
Header面板头内容string \| RenderFragment-
ExpandedIcon自定义切换图标string \| RenderFragment-
Extra自定义渲染每个面板右上角的内容string \| RenderFragment-
ShowArrow是否展示箭头booleantrue
Active面板是否展开,可双向绑定boolean-
ActiveChange面板展开回调EventCallback<boolean>-
Key面板唯一标识string-
OnActiveChange该面板展开状态变化时的回调EventCallback<bool>-

实例方法

名称说明
Activate(string[] activeKeys)展开指定 key 对应的 Panel
Deactivate(string[] inactiveKeys)关闭指定 key 对应的 Panel

Activate / Deactivate 方法在源码 Collapse.razor.cs 中实现:Activate 会展开传入 key 对应的面板,并且在手风琴模式下自动收起其余所有面板;Deactivate 则关闭指定 key 的面板。需要注意,在手风琴模式下调用 Activate 传入多个 key 时,后处理的逻辑会让互斥规则自动生效。

四、手风琴模式的底层实现原理

手风琴模式的互斥逻辑并非由 CSS 实现,而是由 Collapse 组件的 TogglePanelState 方法在 C# 侧统一协调,见 Collapse.razor.cs:

internal void TogglePanelState(Panel panel)
{
    if (panel == null) return;

    var newActiveKeys = new List<string>(EffectiveActiveKeys);

    // 手风琴模式:收起其他所有已展开的面板
    if (this.Accordion && !panel.Active)
    {
        this.Items.Where(item => item != panel && item.Active)
            .ForEach(item => item.SetActiveInt(false));
        newActiveKeys.Clear();
    }

    var isActive = !panel.Active;
    panel.SetActiveInt(isActive);

    if (isActive)
    {
        if (!newActiveKeys.Contains(panel.Key))
            newActiveKeys.Add(panel.Key);
    }
    else
    {
        newActiveKeys.Remove(panel.Key);
    }

    var selectedKeys = newActiveKeys.ToArray();

    if (ActiveKeys != null)
    {
        if (ActiveKeysChanged.HasDelegate)
            ActiveKeysChanged.InvokeAsync(selectedKeys);
    }
    else
    {
        _internalActiveKeys = selectedKeys;
    }

    if (OnChange.HasDelegate)
        OnChange.InvokeAsync(selectedKeys);

    if (panel.OnActiveChange.HasDelegate)
        panel.OnActiveChange.InvokeAsync(panel.Active);
}

从源码中可以提炼出手风琴模式的三条核心行为规则:

  1. 点击触发:用户点击面板标题时,Panel 的 OnHeaderClick 方法会调用 Collapse.TogglePanelState(this),前提是面板未被 Disabled 禁用(见 Panel.razor.cs);
  2. 互斥收起:当点击的是一个未展开的面板且处于手风琴模式时,Items.Where(item => item != panel && item.Active) 会找出所有其他处于展开状态的面板并逐一收起;
  3. 状态同步:展开状态会统一汇聚到 ActiveKeys 数组并通过 ActiveKeysChanged、OnChange 回调对外通知,支持受控与双向绑定两种用法。

组件内部通过 EffectiveActiveKeys(ActiveKeys ?? _internalActiveKeys)来决定"受控"与"非受控"两种模式:当外部传入 ActiveKeys 时,组件进入受控状态,面板开关完全由外部数据驱动(对应下文的外控示例);否则使用内部维护的 _internalActiveKeys 作为默认状态。

五、手风琴模式与外控状态结合

手风琴模式同样支持通过 @bind-ActiveKeys 从外部控制展开的面板。官方演示 ControlledActiveKeys.razor 展示了如何用按钮切换面板状态:

<Collapse @bind-ActiveKeys="@_activeKeys">
    <Panel Key="1" Header="This is panel header 1">
        <p>A dog is a type of domesticated animal. ...</p>
    </Panel>
    <Panel Key="2" Header="This is panel header 2">
        <p>A cat is a type of domesticated animal. ...</p>
    </Panel>
    <Panel Key="3" Header="This is panel header 3">
        <p>A bird is a type of wild or domesticated animal. ...</p>
    </Panel>
</Collapse>
<br />
<Space>
    <SpaceItem>
        <Button Type="@ButtonType.Primary" OnClick="@(() => TogglePanel("1"))">Toggle Panel 1</Button>
    </SpaceItem>
    <SpaceItem>
        <Button Type="@ButtonType.Primary" OnClick="@(() => TogglePanel("2"))">Toggle Panel 2</Button>
    </SpaceItem>
    <SpaceItem>
        <Button Type="@ButtonType.Primary" OnClick="@(() => TogglePanel("3"))">Toggle Panel 3</Button>
    </SpaceItem>
</Space>

@code {
    private string[] _activeKeys = Array.Empty<string>();

    private void TogglePanel(string key)
    {
        if (_activeKeys.Contains(key))
        {
            _activeKeys = _activeKeys.Where(k => k != key).ToArray();
        }
        else
        {
            _activeKeys = _activeKeys.Append(key).ToArray();
        }
    }
}

要点:把 Collapse 的 ActiveKeys 通过 @bind- 绑定到组件字段后,展开/折叠完全由外部数组驱动。若将该示例与 Accordion 属性组合使用,即可在受控状态下获得手风琴的互斥效果——此时外部每次只应向 ActiveKeys 保留一个 key。

六、手风琴模式下的面板定制

手风琴模式的每个 Panel 依然支持全部自定义能力,常见的组合方式如下:

  • 隐藏箭头:设置 ShowArrow="false",面板标题栏不再显示展开箭头(对应 noarrow.md 演示);
  • 无边框:在 Collapse 上设置 Bordered="false",组件会添加 ant-collapse-borderless 样式类(见 Collapse.razor.cs 的 SetClassMap),形成紧凑无边框布局;
  • 自定义右侧内容:Panel 的 Extra / ExtraTemplate 参数用于渲染面板右上角的内容,渲染位置由 Panel.razor 中的 ant-collapse-extra 容器承载;
  • 自定义图标:ExpandIconTemplate 接收一个 bool(当前面板是否展开)参数,可据此动态渲染图标;未设置时默认使用 Collapse.ExpandIcon 指定的图标(默认 IconType.Outline.Right),并通过 Rotate 在展开/收起时旋转 90°;
  • 禁用面板:Panel 设置 Disabled 后,点击标题不会触发任何展开操作(源码中 OnHeaderClick 会直接跳过)。

需要注意的是,手风琴模式下仍可以嵌套使用 Collapse:外层手风琴的某个面板内部可以再放一个独立的 Collapse 甚至又一个手风琴(参考 Mix.razor 演示),各层级的展开状态互不影响。

七、动画与视觉细节

  • Collapse 的 Animation 属性默认关闭。开启后,面板展开/收起会走 Panel.razor.cs 中的 HandleExpand / HandleCollapse 动画流程:通过 JS 互操作读取内容区高度,配合 ant-motion-collapse-* 系列样式类与 height/opacity 过渡实现平滑展开收起,动画总时长约 550ms(100ms 启动 + 450ms 过渡);
  • 箭头位置由 ExpandIconPosition 控制(left / right),对应的样式类为 ant-collapse-icon-position-left / ant-collapse-icon-position-right;
  • RTL 场景下组件会自动追加 ant-collapse-rtl 样式类。

八、总结与选择建议

场景推荐配置
同时展示多个独立内容区默认模式,不设置 Accordion
空间受限、每次只聚焦一个内容区设置 Accordion(本文核心)
需要外部按钮控制开关组合使用 @bind-ActiveKeys 与外控逻辑
紧凑型信息展示Accordion + Bordered="false"
需要平滑过渡Accordion + Animation="true"

手风琴模式是 Collapse 组件在"内容互斥展示"场景下的标准答案。它由 Collapse.razor.cs 中的 TogglePanelState 在 C# 侧统一管理互斥逻辑,配合 DefaultActiveKey、ActiveKeys、OnChange 等参数即可覆盖从"开箱即用"到"完全受控"的各类需求;结合 Panel 的 Header、Extra、ShowArrow、Disabled 等参数,可以定制出贴合业务形态的手风琴交互。动手实践时,可直接参考官方演示 Accordion.razor 与完整 API 文档 index.zh-CN.md。

  • 前端
  • UI组件
  • 设计系统

【免费下载链接】ant-design-blazor

基于 Ant Design 与 Blazor 的前端组件库。让开发者解放生产力,实现更大价值。

项目地址: https://gitcode.com/ant-design-blazor/ant-design-blazor
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值