ng-zorro-antd 21.3.0:Cascader 弹层自定义与 Open 受控终于对齐

2026-05-22 19 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:6 分钟

ng-zorro-antd 21.3.0 刚刚落地,这次更新集中在 Cascader(级联选择)组件上——补上了 nzPopupRender 属性,并把 Open 受控行为与 Ant Design React 版对齐。对于做中后台表单的开发者来说,这两个改动直接解决了之前"弹层里塞自定义内容要 hack"和"手动控制展开状态行为不一致"的老问题。

nzPopupRender:弹层里终于能放自定义内容

之前想在级联选择的弹出面板里加个搜索框、统计信息或操作按钮,要么用 ng-template 配合内部 API 绞尽脑汁,要么干脆放弃。21.3.0 新增的 nzPopupRender 属性,让你直接往弹层底部追加自定义模板,用法和 Ant Design React 版的 dropdownRender 一脉相承。

核心用法:

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-cascader-demo',
  template: `
    <nz-cascader
      [nzOptions]="options"
      [nzPopupRender]="popupFooter"
      [(ngModel)]="selectedValue"
      nzPlaceHolder="请选择地区"
    ></nz-cascader>

    <ng-template #popupFooter>
      <div class="popup-footer" style="padding: 8px 12px; border-top: 1px solid #f0f0f0;">
        <button nz-button nzSize="small" nzType="link" (click)="clearSelection()">
          清空选择
        </button>
        <span style="float: right; color: #999; font-size: 12px;">
          共 {{ options.length }} 个省份
        </span>
      </div>
    </ng-template>
  `
})
export class CascaderDemoComponent {
  selectedValue: string[] | null = null;

  options = [
    {
      value: 'zhejiang',
      label: '浙江',
      children: [
        { value: 'hangzhou', label: '杭州', children: [{ value: 'xihu', label: '西湖' }] },
        { value: 'ningbo', label: '宁波' }
      ]
    },
    {
      value: 'jiangsu',
      label: '江苏',
      children: [
        { value: 'nanjing', label: '南京' },
        { value: 'suzhou', label: '苏州' }
      ]
    }
  ];

  clearSelection(): void {
    this.selectedValue = null;
  }
}

几个注意点:

  • nzPopupRender 接收的是 ng-template 引用,不是字符串或组件。
  • 自定义内容追加在级联面板底部,不会覆盖原有的列结构。
  • 样式上建议用 Ant Design 的间距和分割线变量(#f0f0f08px 12px),保持视觉一致。

Open 受控行为对齐:不再有"关不掉"的尴尬

之前 Angular 版 Cascader 的 nzOpen 受控行为和 React 版不一致——你设了 nzOpenfalse,面板可能还是不收起,或者双向绑定的时机不对。21.3.0 把这块逻辑对齐到了 Ant Design 的规范:当你显式绑定 nzOpen,组件就完全由你控制展开/收起状态

典型场景:表单联动,选择某个选项后自动收起面板,或者根据外部条件强制展开。

// controlled-open.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-controlled-cascader',
  template: `
    <nz-cascader
      [nzOptions]="options"
      [(ngModel)]="selectedValue"
      [nzOpen]="isCascaderOpen"
      (nzOpenChange)="onOpenChange($event)"
      nzPlaceHolder="选择后自动收起"
    ></nz-cascader>

    <button nz-button (click)="forceOpen()" style="margin-left: 12px;">
      外部触发展开
    </button>
  `
})
export class ControlledCascaderComponent {
  selectedValue: string[] | null = null;
  isCascaderOpen = false;

  options = [
    { value: 'beijing', label: '北京', children: [{ value: 'haidian', label: '海淀' }] },
    { value: 'shanghai', label: '上海', children: [{ value: 'pudong', label: '浦东' }] }
  ];

  onOpenChange(open: boolean): void {
    // 用户点击了面板外部或选择了叶子节点,面板请求收起
    this.isCascaderOpen = open;
  }

  forceOpen(): void {
    this.isCascaderOpen = true;
  }
}

对齐后的行为要点:

场景 之前的行为 对齐后的行为
nzOpen=false 绑定 面板可能仍可见 面板立即收起
用户选完叶子节点 nzOpenChange 不一定触发 正常触发 false,你决定是否收起
外部强制 nzOpen=true 需要额外 hack 直接生效

关键提醒:受控模式下,你必须处理 nzOpenChange 事件来更新 nzOpen 的值,否则面板状态会"卡住"。这是所有受控组件的通用规则,不只是 Cascader。

升级实操

从 20.x 或更早版本升级到 21.3.0,步骤很简单:

# 1. 确认 Angular 版本——ng-zorro 21.x 对应 Angular 17+
ng version

# 2. 更新 ng-zorro-antd
npm install ng-zorro-antd@21.3.0

# 3. 如果用了 Cascader,检查以下两点:
#    - 有没有手动 hack 弹层内容的代码 → 改用 nzPopupRender
#    - 有没有 nzOpen 双向绑定 [(nzOpen)] → 改为单向 [nzOpen] + (nzOpenChange)

升级检查清单:

  • ✅ Cascader 的 nzOpen 如果用了双向绑定 [(nzOpen)],拆成单向受控 + 事件处理。
  • ✅ 任何通过 CSS hack 或 overlay 直接操作弹层 DOM 的代码,迁移到 nzPopupRender
  • ✅ 其他组件无破坏性变更,正常升级即可。
  • ✅ MIT 协议不变,企业项目无需额外授权。

ng-zorro-antd 21.3.0 的改动不大但很精准——Cascader 的两个痛点一次性解决。如果你的中后台项目里有级联选择器,这次升级值得立刻做。


相关推荐