- UI组件
- 前端
【免费下载链接】ng-zorro-antd
Angular UI Component Library based on Ant Design
导读
在 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] | 设置按钮的加载状态 | boolean | false |
在 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>要点解读:
- 属性形式
nzLoading等价于[nzLoading]="true",由booleanAttribute转换保证; - 按钮内原有的图标(如
nz-icon nzType="poweroff")会被自动隐藏,改为显示旋转的 loading 图标(详见下文“图标替换原理”); - 加载中按钮默认渲染为
primary类型,可与nzSize="small"、nzShape="circle"等属性自由组合; 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'); } }); }机制说明:
@ContentChild(NzIconDirective, { read: ElementRef })捕获按钮内容中的第一个nz-icon元素(button.component.ts);ngOnChanges中每次nzLoading变化都会向loading$主题推送新值(button.component.ts);- 加载时对原图标设置
display: none,恢复时移除该内联样式; - 测试用例 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> |
两个额外提示:
- 加载期间不必再手动加
disabled:nzLoading已自带点击拦截,二者语义重叠;如果同时设置,拦截逻辑同样生效; - 样式一致性:演示代码通过
[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
相关推荐
ng-zorro-antd Button 组件实战指南:五种按钮类型与状态属性的完整解析
ng zorro antd Button 组件实战指南:五种按钮类型与状态属性的完整解析 本指南以 ng zorro antd 官方按钮基础示例 compone
UI组件前端ng-zorro-antd 卡片预加载实战:nz-card 的 nzLoading 加载占位与 Skeleton 骨架屏方案
ng zorro antd 卡片预加载实战:nz card 的 nzLoading 加载占位与 Skeleton 骨架屏方案 数据读入前展示加载占位是 Angu
UI组件前端ng-zorro-antd Cascader 自定义校验状态(nzStatus)实战指南
ng zorro antd Cascader 自定义校验状态(nzStatus)实战指南 nzStatus 是 ng zorro antd Cascader(级
UI组件前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考