news 2026/9/25 14:44:37

ng-zorro-antd Button 加载中状态(nzLoading)完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ng-zorro-antd Button 加载中状态(nzLoading)完整实战指南
  • UI组件
  • 前端

【免费下载链接】ng-zorro-antd

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载

导读

在 Angular 应用中使用 ng-zorro-antd 的 Button 组件时,nzLoading属性可以一键让按钮进入“加载中”状态:按钮内自动渲染旋转的 loading 图标、文字前插入间隔、并且在加载期间拦截一切点击事件,从根源上避免表单重复提交或操作被并发触发。本篇指南以官方演示 loading.md 与配套示例 loading.ts 为主体,结合 button.component.ts 的源码实现与 button.spec.ts 的测试用例,系统讲解nzLoading的静态用法、动态切换、圆形按钮适配,以及其底层的事件拦截与图标替换原理。读完本文,你将能够在自己项目中正确、安全地使用按钮加载状态,并理解其背后的设计约束。

一、nzLoading是什么:一句话看懂用法

按官方文档的表述:“添加nzLoading属性即可让按钮处于加载状态”(A loading indicator can be added to a button by setting thenzLoadingproperty on thenz-button)。nz-button在 ng-zorro-antd 中是一个指令,支持原生 button 的全部属性,加载状态只是其众多能力中的一项。

从 API 文档 可以看到nzLoading的完整定义:

属性说明类型默认值
[nzLoading]设置按钮的加载状态booleanfalse

在 button.component.ts 中,该输入被声明为:

@Input({ transform: booleanAttribute }) nzLoading: boolean = false;

这意味着:

  • 默认值为false,按钮处于可交互状态;
  • 采用booleanAttribute转换,因此写法上既可以写属性形式<button nz-button nzLoading>,也可以写属性绑定形式[nzLoading]="true",两者等价;
  • 与nzBlock、nzGhost、nzDanger一样属于布尔型开关(见 button.component.ts)。

二、基本用法:让按钮立即进入加载中状态

最直接的用法是在按钮上静态设置nzLoading,按钮一经渲染即处于加载中。官方演示 loading.ts 展示了两种形态:

<button nz-button nzType="primary" nzLoading> <nz-icon nzType="poweroff" /> Loading </button> <button nz-button nzType="primary" nzSize="small" nzLoading>Loading</button>

要点解读:

  1. 属性形式nzLoading等价于[nzLoading]="true",由booleanAttribute转换保证;
  2. 按钮内原有的图标(如nz-icon nzType="poweroff")会被自动隐藏,改为显示旋转的 loading 图标(详见下文“图标替换原理”);
  3. 加载中按钮默认渲染为primary类型,可与nzSize="small"、nzShape="circle"等属性自由组合;
  4. NzIconModule需要随组件一起导入,因为 loading 图标本身就是一个nz-icon(演示代码中imports: [NzButtonModule, NzIconModule]即为此目的)。

三、动态切换:点击后进入加载、任务结束自动恢复

更常见的业务场景是“点击提交 → 进入加载 → 请求完成后恢复”。官方演示的最后两个按钮演示了这一点(loading.ts):

<button nz-button nzType="primary" [nzLoading]="loadings()[0]" (click)="enterLoading(0)">Click me!</button> <button nz-button nzType="primary" [nzLoading]="loadings()[1]" (click)="enterLoading(1)"> <nz-icon nzType="poweroff" /> Click me! </button>

对应的组件逻辑(loading.ts)使用了 Angular 的 signal:

readonly loadings = signal<boolean[]>([false, false]); enterLoading(index: number): void { const update = (index: number, loading: boolean): void => { this.loadings.update(loadings => loadings.map((item, i) => (i === index ? loading : item))); }; update(index, true); setTimeout(() => update(index, false), 3000); }

这里的实现要点:

  • 用signal<boolean[]>分别维护两个按钮的加载状态,点击时通过enterLoading(index)将对应下标置为true;
  • 示例中用setTimeout(..., 3000)模拟 3 秒异步任务,任务结束后置回false;
  • 真实项目中,应把update(index, true)放在异步请求发起前,把update(index, false)放在请求的finally回调中,确保无论成功失败都能恢复按钮;
  • 两个按钮状态互相独立,可同时处于加载状态,因此数组化管理比单个布尔值更贴合多按钮场景。

四、圆形按钮(Icon Only)与加载状态

当按钮只包含一个图标、不包含文字时,nzLoading依然能正常工作,且组件会自动识别为“仅图标”形态。官方演示(loading.ts):

<button nz-button nzLoading nzShape="circle"></button> <button nz-button nzLoading nzType="primary" nzShape="circle"></button>

从源码看,这类按钮会被同时加上ant-btn-circle与ant-btn-loading两个类(见 button.component.ts),loading 图标居中显示,形成典型的圆形加载按钮。测试用例 button.spec.ts 专门验证了nzLoading与图标按钮的组合会正确得到ant-btn-icon-only类。

五、源码原理(一):加载图标如何渲染

nzLoading生效时,按钮模板会额外渲染一个 loading 图标节点(button.component.ts):

template: ` @if (nzLoading) { <span class="ant-btn-icon ant-btn-loading-icon"> <nz-icon nzType="loading" /> </span> } <ng-content /> `,

结合 button.component.ts 的 host 绑定'[class.ant-btn-loading]': nzLoading,当nzLoading为真时:

  • 按钮元素获得ant-btn-loading类,样式层通过旋转动画让ant-btn-loading-icon内的nz-icon持续转动;
  • 模板中的<ng-content />依然输出你写在按钮内部的内容(文字、原有图标等),但原有图标会被“隐藏替换”(见下文);
  • 由于nz-icon nzType="loading"本身是一个旋转动画图标,所以无需额外 JS,仅靠 CSS 即可呈现加载动效。

六、源码原理(二):原有图标自动隐藏的机制

细心的读者会发现:第一个演示按钮里同时写了<nz-icon nzType="poweroff" />,但加载时显示的是 loading 图标而非 poweroff。这是通过loading$主题与内容子查询实现的(button.component.ts):

ngAfterContentInit(): void { this.loading$ .pipe( startWith(this.nzLoading), filter(() => !!this.nzIconDirectiveElement), takeUntilDestroyed(this.destroyRef) ) .subscribe(loading => { const nativeElement = this.nzIconDirectiveElement.nativeElement; if (loading) { this.renderer.setStyle(nativeElement, 'display', 'none'); } else { this.renderer.removeStyle(nativeElement, 'display'); } }); }

机制说明:

  1. @ContentChild(NzIconDirective, { read: ElementRef })捕获按钮内容中的第一个nz-icon元素(button.component.ts);
  2. ngOnChanges中每次nzLoading变化都会向loading$主题推送新值(button.component.ts);
  3. 加载时对原图标设置display: none,恢复时移除该内联样式;
  4. 测试用例 button.spec.ts 完整验证了这一行为:点击前 poweroff 图标可见、无ant-btn-loading类;点击后出现ant-btn-loading-icon且 poweroff 元素内联样式变为display: none;;计时器推进后一切恢复原状。

七、源码原理(三):加载期间拦截点击,杜绝重复提交

nzLoading最实用的价值在于加载状态下按钮不可再被点击。这一点由构造函数中注册的捕获阶段事件监听保证(button.component.ts):

fromEventOutsideAngular<MouseEvent>(this.elementRef.nativeElement, 'click', { capture: true }) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(event => { if ((this.disabled && (event.target as HTMLElement)?.tagName === 'A') || this.nzLoading) { event.preventDefault(); event.stopImmediatePropagation(); } });

关键行为:

  • 事件监听注册在capture(捕获)阶段,且运行在 Angular 变更检测之外,因此拦截开销极小;
  • 只要nzLoading为真,点击事件会被preventDefault()阻止默认行为,并用stopImmediatePropagation()阻止事件继续传播——业务侧绑定的(click)处理器不会被触发,从根源上避免重复提交;
  • 测试 button.spec.ts 明确断言:按钮处于加载状态时点击,preventDefault与stopImmediatePropagation各被调用一次;
  • 同段逻辑也处理了 disabled 状态下<a nz-button>锚点按钮的点击拦截(button.spec.ts 有对应锚点测试)。

八、与其他属性的组合实战建议

nzLoading可与 Button 其余属性自由组合,常用搭配如下(属性完整定义见 API 文档):

组合典型场景示例
nzLoading+nzType="primary"表单主提交按钮,加载中凸显主要动作<button nz-button nzType="primary" nzLoading>提交中</button>
nzLoading+nzSize="small"列表行内操作按钮(如“删除中”)<button nz-button nzSize="small" [nzLoading]="delLoading">删除</button>
nzLoading+nzShape="circle"纯图标按钮(如刷新、导出)<button nz-button nzShape="circle" [nzLoading]="refreshLoading"></button>
nzLoading+nzDanger危险操作二次确认后的执行中状态<button nz-button nzDanger [nzLoading]="loading">确认删除</button>
nzLoading+nzBlock占满整行的提交按钮<button nz-button nzBlock nzType="primary" [nzLoading]="loading">登录</button>

两个额外提示:

  1. 加载期间不必再手动加disabled:nzLoading已自带点击拦截,二者语义重叠;如果同时设置,拦截逻辑同样生效;
  2. 样式一致性:演示代码通过[nz-button] { margin-inline-end: 8px; margin-bottom: 12px; }统一了按钮间距(loading.ts),多按钮并排时建议保持类似约定,避免加载图标切换时布局跳动。

九、可继续深入阅读的仓库资源

若希望进一步探究实现细节与更多按钮用法,可在当前仓库中查阅以下文件:

  • 示例实现:components/button/demo/loading.ts(本文全部代码示例来源)
  • 组件源码:components/button/button.component.ts(nzLoading输入、模板渲染、点击拦截、图标替换的全部实现)
  • 单元测试:components/button/button.spec.ts(loading 类名、图标隐藏、点击拦截的行为验证)
  • API 文档:components/button/doc/index.en-US.md(nz-button全部属性、类型与默认值)
  • 样式入口:components/button/style/index.less(ant-btn-loading相关视觉样式)
  • 其他按钮演示:components/button/demo/basic.ts(五种类型按钮基础用法,可对照学习)
  • UI组件
  • 前端

【免费下载链接】ng-zorro-antd

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载
上一篇:WeChatMsg 微信聊天记录导出教程:免费备份记录,生成年度聊天报告
下一篇:技术解析:Realtek RTL8821CU Linux无线网卡驱动架构与实现

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 14:43:22

Atlas 300V 24G推理加速卡部署YOLOv5:从模型转换到性能调优实战

1. 先搞清楚&#xff1a;Atlas 300V 24G到底是不是运算加速卡最近不少做视觉算法落地的朋友在问Atlas&#xff0c;特别是Atlas 300V 24G这张卡。问题集中在两个&#xff1a;这玩意儿到底算不算运算加速卡&#xff0c;以及它能不能拿来部署YOLO。我今天就把这块卡从头到尾聊透—…

作者头像 李华
网站建设 2026/9/25 14:38:29

多智能体协同工程化实战:角色拆分、通信契约与上下文管理

1. 从"一个模型打天下"到"一支队伍打硬仗"&#xff1a;多智能体协同到底在解决什么如果你最近半年在关注 AI 研发的工程化落地&#xff0c;大概率会反复撞见一个词——多智能体协同。但真正让我决定动手写这篇总结的&#xff0c;不是概念本身有多热&#x…

作者头像 李华
网站建设 2026/9/25 14:34:53

通信型CRM如何重塑客户跟进流程:坐席工作台与客户时间线实践复盘

做客服团队管理这几年&#xff0c;我一直有个执念&#xff1a;客户跟进的上下文绝对不能断。2024年下半年&#xff0c;我们整个客服和销售运营从“微信Excel传统呼叫平台”的混合方案&#xff0c;迁移到了DeskcommCRM&#xff0c;到现在跑了快九个月。整个过程从选型到落地&…

作者头像 李华