news 2026/9/29 7:58:57

ng-zorro-antd Table 列筛选与排序完全指南:从 `nzFilters` 到 `nzSortDirections` 的前端表格数据处理方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ng-zorro-antd Table 列筛选与排序完全指南:从 `nzFilters` 到 `nzSortDirections` 的前端表格数据处理方案
  • UI组件
  • 前端

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

Angular UI Component Library based on Ant Design

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

导读

本文基于 ng-zorro-antd 官方示例 components/table/demo/sort-filter.md 及其配套示例代码 sort-filter.ts,系统讲解 ng-zorro-antd Table 组件中「列筛选」与「列排序」两大高频能力的完整用法。你将掌握通过nzFilters/nzFilterFn/nzFilterMultiple构建多选与单选筛选菜单、通过nzSortOrder/nzSortFn/nzSortDirections定制排序行为,并理解这些指令在源码中的底层执行链路(table-data.service.ts),从而在真实业务中快速落地可交互的筛选排序表格。

一、功能概览:筛选与排序在 Table 中的定位

ng-zorro-antd 的 Table 组件将「列头交互」拆分为两个正交的能力维度,二者可以独立使用、也可以在同一列上叠加:

  • 筛选(Filter):为某一列定义一组筛选项,用户点击列头筛选图标后,通过勾选/单选的方式限定显示哪些行。核心指令是nzFilters、nzFilterFn、nzFilterMultiple。
  • 排序(Sort):为某一列定义一个比较函数,用户点击列头在不同排序方向间切换。核心指令是nzSortOrder、nzSortFn、nzSortDirections。

这些指令均声明在th元素上,由 th-addon.component.ts 统一接管。该组件的选择器明确列出了支持的属性组合:

th[nzColumnKey], th[nzSortFn], th[nzSortOrder], th[nzFilters], th[nzShowSort], th[nzShowFilter], th[nzCustomFilter]

也就是说,只要某个th上出现了上述任一属性,表格就会为该列启用对应的列头附加能力。

二、筛选(Filter):定义筛选项、筛选逻辑与多选/单选

2.1 三个核心指令的职责

指令类型作用
nzFiltersNzTableFilterList定义筛选菜单中的筛选项列表,每项为{ text: string; value: NzSafeAny; byDefault?: boolean }
nzFilterFnNzTableFilterFn<T>筛选函数,(value: NzTableFilterValue, data: T) => boolean,决定某行数据是否被保留
nzFilterMultipleboolean是否支持多选,true(默认)为多选,false为单选

其中类型定义位于 table.types.ts:

export type NzTableFilterList = Array<{ text: string; value: NzSafeAny; byDefault?: boolean }>; export type NzTableFilterValue = NzSafeAny[] | NzSafeAny; export type NzTableFilterFn<T = unknown> = (value: NzTableFilterValue, data: T) => boolean;

2.2 一个可直接运行的最小示例

以下代码取自官方示例 sort-filter.ts,演示了「Name」列的多选筛选 + 「Address」列的单选筛选:

import { Component } from '@angular/core'; import { NzTableFilterFn, NzTableFilterList, NzTableModule } from 'ng-zorro-antd/table'; interface ItemData { name: string; age: number; address: string; } @Component({ selector: 'nz-demo-table-sort-filter', imports: [NzTableModule], template: ` <nz-table #filterTable [nzData]="listOfData" nzTableLayout="fixed"> <thead> <tr> <th [nzFilterMultiple]="true" [nzFilters]="[{ text: 'Joe', value: 'Joe' }, { text: 'Jim', value: 'Jim', byDefault: true }]" [nzFilterFn]="(list: string[], item: ItemData) => list.some(name => item.name.indexOf(name) !== -1)" >Name</th> <th [nzFilterMultiple]="false" [nzFilters]="[{ text: 'London', value: 'London' }, { text: 'Sidney', value: 'Sidney' }]" [nzFilterFn]="(address: string, item: ItemData) => item.address.indexOf(address) !== -1" >Address</th> </tr> </thead> <tbody> @for (data of filterTable.data; track data) { <tr><td>{{ data.name }}</td><td>{{ data.address }}</td></tr> } </tbody> </nz-table> ` }) export class NzDemoTableSortFilterComponent { /* ... */ }

要点说明:

  • 模板中通过#filterTable拿到组件引用,直接用filterTable.data渲染经过筛选/排序之后的数据——这是 ng-zorro-antd Table「受控数据 + 内部计算」模式的典型用法;
  • nzFilterMultiple = true时,nzFilterFn收到的第一个参数是选中值组成的数组(如['Joe', 'Jim']);nzFilterMultiple = false时收到的是单个值(如'London')。因此示例中 Name 列用list.some(...)遍历数组,而 Address 列直接对单个字符串做indexOf判断;
  • 单选用例中「Address」列的筛选值为'London',item.address.indexOf('London') !== -1实现包含匹配,适合地址这类长文本的模糊筛选。

2.3 默认启用筛选:byDefault

官方文档强调:通过在nzFilters某个筛选项上设置{ byDefault: true },可以让表格在初始化时就默认应用该筛选条件。示例中「Jim」这一项即为默认筛选:

listOfFilter: [ { text: 'Joe', value: 'Joe' }, { text: 'Jim', value: 'Jim', byDefault: true } ]

底层实现见 filter.component.ts,parseListOfFilter在解析筛选项时会读取byDefault来初始化勾选状态:

parseListOfFilter(listOfFilter: NzTableFilterList, reset?: boolean): NzThItemInterface[] { return listOfFilter.map(item => { const checked = reset ? false : !!item.byDefault; return { text: item.text, value: item.value, checked }; }); }

同时在 th-addon.component.ts 中,组件初始化时会从byDefault项中提取默认筛选值:

const listOfValue = this.nzFilters.filter(item => item.byDefault).map(item => item.value); this.nzFilterValue = this.nzFilterMultiple ? listOfValue : listOfValue[0] || null;

注意这里多选模式下默认值是一个数组,单选模式下取第一个byDefault项的值;当单选且没有任何byDefault项时,默认值为null(即不筛选)。如果你想重置筛选状态,可以结合 reset-filter 示例 通过外部按钮清空筛选值。

2.4 筛选菜单的交互与确认机制

点击列头筛选图标后弹出的菜单由nz-table-filter组件渲染(filter.component.ts):

  • 多选模式下每项渲染为nz-checkbox,单选模式下渲染为nz-radio(模板见 filter.component.ts);
  • 底部提供「重置」与「确定」两个按钮,文案来自 i18n 的locale.filterReset/locale.filterConfirm,支持多语言;
  • 选中变化并不会立即生效,而是在点击「确定」或关闭菜单时通过emitFilterData触发filterChange事件,保证交互的确定性;
  • onFilterValueChange收到筛选值后,在 th-addon.component.ts 中同步到nzFilterValue并触发updateCalcOperator(),驱动下游数据计算。

三、排序(Sort):默认顺序、比较函数与可用方向

3.1 三个核心指令的职责

指令类型作用
nzSortOrderNzTableSortOrder当前排序状态/默认排序方向,取值为'ascend'、'descend'或null(不排序)
nzSortFnNzTableSortFn<T>排序比较函数,(a: T, b: T, sortOrder?: NzTableSortOrder) => number,返回正/负/零表示 a 与 b 的先后关系
nzSortDirectionsNzTableSortOrder[]定义点击列头时依次循环切换的排序方向序列

类型定义见 table.types.ts:

export type NzTableSortOrder = string | 'ascend' | 'descend' | null; export type NzTableSortFn<T = unknown> = (a: T, b: T, sortOrder?: NzTableSortOrder) => number;

3.2 排序方向的三态循环机制

nzSortDirections默认值为['ascend', 'descend', null](见 th-addon.component.ts),即点击列头依次经历:升序 → 降序 → 取消排序 → 升序……。如果你希望「降序之后直接回到无排序」,可以把该列配置为['descend', null]。

方向切换的核心逻辑getNextSortDirection位于 th-addon.component.ts:

getNextSortDirection(sortDirections: NzTableSortOrder[], current: NzTableSortOrder): NzTableSortOrder { const index = sortDirections.indexOf(current); if (index === sortDirections.length - 1) { return sortDirections[0]; } else { return sortDirections[index + 1]; } }

用户在列头上点击时,th会监听 click 事件并按上述序列推进排序方向(th-addon.component.ts),同时通过nzSortOrderChange事件对外通知。

3.3 默认排序与比较函数示例

示例中「Age」列通过sortOrder: 'descend'指定了默认降序,并给出数值比较函数:

{ name: 'Age', sortOrder: 'descend', sortFn: (a: ItemData, b: ItemData) => a.age - b.age, sortDirections: ['descend', null] }
  • 数字列直接使用a.age - b.age即可得到标准的比较结果;
  • 字符串列建议使用a.name.localeCompare(b.name)(示例 Name 列),以获得符合语言环境的字典序比较;
  • 该列配置了['descend', null],所以首次渲染即处于降序状态,再次点击会取消排序,适合「默认按最新数据倒序展示」的场景。

3.4 排序与筛选共用同一列头

ng-zorro-antd 允许同一列同时配置筛选与排序,示例中 Name 列就同时具备两者:

{ name: 'Name', sortFn: (a: ItemData, b: ItemData) => a.name.localeCompare(b.name), sortDirections: ['ascend', 'descend', null], filterMultiple: true, listOfFilter: [ /* 筛选项 */ ], filterFn: (list: string[], item: ItemData) => /* 筛选逻辑 */ }

当排序与筛选同时启用时,列头会先展示筛选图标、再展示排序指示符(向上/向下箭头),二者互不干扰,筛选与排序会按「先筛选、后排序」的顺序依次作用于数据(见下文源码链路)。

四、源码纵深:筛选与排序如何驱动数据计算

4.1 计算操作符的收集

每个th的附加能力组件(th-addon.component.ts)在输入属性变化时调用updateCalcOperator(),把「筛选值 + 筛选函数」「排序方向 + 排序函数 + 排序优先级」登记为计算操作符。ngOnChanges中还会做两件值得注意的事情:

  1. 自动启用排序/筛选显示:当nzSortOrder或nzSortFn首次被设置且未显式声明nzShowSort时,会自动将nzShowSort置为true;同理,首次设置nzFilters且未声明nzShowFilter时,会自动开启筛选图标(th-addon.component.ts)。也就是说,只要绑定了排序或筛选相关属性,列头 UI 就会自动出现。
  2. 配置中心支持:nzSortDirections声明了@WithConfig(),意味着可以通过全局NzConfigService的table配置项统一修改默认排序方向序列(参见 th-addon.component.ts 与 #L102)。

4.2 数据管线:先筛选、后排序

真正执行筛选与排序的流水线位于 table-data.service.ts,它通过 RxJScombineLatest组合「原始数据流」与「计算操作符流」,对每一份数据做如下处理:

// 1) 收集所有"未被重置"的筛选操作符并依次过滤 const listOfFilterOperator = listOfCalcOperator.filter(item => { const { filterValue, filterFn } = item; const isReset = filterValue === null || filterValue === undefined || (Array.isArray(filterValue) && filterValue!.length === 0); return !isReset && typeof filterFn === 'function'; }); for (const item of listOfFilterOperator) { listOfDataAfterCalc = listOfDataAfterCalc.filter(data => (filterFn as NzTableFilterFn<T>)(filterValue, data)); } // 2) 按 sortPriority 降序排列排序操作符,再逐列比较 const listOfSortOperator = listOfCalcOperator .filter(item => item.sortOrder !== null && typeof item.sortFn === 'function') .sort((a, b) => +b.sortPriority - +a.sortPriority); if (listOfCalcOperator.length) { listOfDataAfterCalc.sort((record1, record2) => { for (const item of listOfSortOperator) { const compareResult = (sortFn)(record1, record2, sortOrder); if (compareResult !== 0) { return sortOrder === 'ascend' ? compareResult : -compareResult; } } return 0; }); }

从源码可以确认两个重要行为:

  • 筛选先于排序执行:所有满足条件的筛选函数依次对数据做filter,剩余行再进入排序阶段;
  • 升序/降序的实现方式:排序函数sortFn本身只返回标准的「负/零/正」比较结果,若当前方向是descend,服务会对比较结果取反(return sortOrder === 'ascend' ? compareResult : -compareResult),因此你无需在sortFn里区分方向,只需写好一种比较逻辑即可。

排序阶段还支持多列排序:多个列的排序函数按照nzSortPriority(数字越大优先级越高)依次比较,只有前一列比较结果相等时才会进入下一列。想深入了解多列排序可参考官方示例 multiple-sorter.ts,其中通过priority: 3 / 2 / 1让语文、数学、英语成绩列按优先级依次参与排序,priority: false的列则完全不参与多列排序。

4.3 前端分页下的数据切片

筛选与排序作用于「全量数据」,之后再由分页逻辑按pageIndex与pageSize切片得到当前页数据(table-data.service.ts)。也就是说:当[nzFrontPagination](默认开启)时,排序和筛选会先作用于全部数据,再进行分页;如果你改为[nzFrontPagination]="false",服务端模式下的排序与筛选仅通过queryParams向外传递,由后端自行处理(table-data.service.ts)。这一取舍在决定「前端排序还是服务端排序」时非常关键。

五、进阶组合技巧与常见问题

5.1 常用配置速查

需求配置写法
数字列升/降序[nzSortFn]="(a, b) => a.age - b.age",[nzSortDirections]="['ascend', 'descend', null]"
字符串列字典序[nzSortFn]="(a, b) => a.name.localeCompare(b.name)"
默认降序且不允许取消[nzSortOrder]="'descend'",[nzSortDirections]="['descend']"
多选筛选[nzFilterMultiple]="true",筛选函数接收string[]
单选筛选[nzFilterMultiple]="false",筛选函数接收单个值
默认勾选某个筛选项在nzFilters项中加byDefault: true
筛选值从外部受控监听(nzFilterChange)事件,自行更新nzFilters/nzFilterValue

5.2 常见问题排查

  • 列头不显示排序/筛选图标:确认是否显式声明了[nzShowSort]="true"/[nzShowFilter]="true",或绑定了nzSortFn/nzFilters等属性(源码会自动开启,见 th-addon.component.ts);
  • 筛选不生效:检查nzFilterFn第一个参数类型是否与nzFilterMultiple匹配——多选是数组、单选是单值;同时确认筛选项的value与数据字段类型一致;
  • 排序方向不对:确认nzSortDirections中是否包含null以支持取消排序;确认sortFn返回的是标准比较结果(排序服务会自动处理升降序取反);
  • 默认筛选未生效:确认byDefault写在nzFilters的项对象上({ text, value, byDefault: true }),且该列没有在外部反复重置筛选值。

5.3 扩展到自定义筛选与受控表格

  • 如果默认的筛选菜单不满足需求,可通过[nzCustomFilter]="true"+nz-th-extra内容投影自定义整个筛选面板(实现参考 th-addon.component.ts 的extraTemplate插槽);
  • 若筛选与排序需要完全受外部状态控制(例如与服务端分页配合),可以在nz-table上监听(nzQueryParams)事件获取形如{ pageIndex, pageSize, sort: [{key, value}], filter: [{key, value}] }的查询参数对象(类型见 table.types.ts),再据此发起请求。

六、参考资料

  • 官方示例文档:components/table/demo/sort-filter.md
  • 配套示例源码:components/table/demo/sort-filter.ts
  • 类型定义:components/table/src/table.types.ts
  • 列头附加能力实现:components/table/src/cell/th-addon.component.ts
  • 筛选菜单实现:components/table/src/addon/filter.component.ts
  • 数据计算与排序管线:components/table/src/table-data.service.ts
  • 多列排序示例:components/table/demo/multiple-sorter.ts
  • 重置筛选示例:components/table/demo/reset-filter.ts
  • UI组件
  • 前端

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

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载
上一篇:7步精通Adobe-GenP:从创意工作者痛点到专业工具解放全攻略
下一篇:Betaflight Configurator终极指南:无人机飞控配置的完整解决方案

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

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

TRAE国际版团队开发配置:用TaoToken统一Key打通多人协作环境

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 7:58:13

Mermaid画甘特图

文章目录甘特图基本语法dateFormat格式axisFormat格式甘特图 甘特图从外观来看&#xff0c;是一种水平条形图&#xff0c;其横轴表示时间&#xff0c;纵轴表示任务&#xff0c;从而直观展示项目进度计划。简单示例如下 #mermaid-svg-t5f5AXFpTQu0uJDW{font-family:"trebuc…

作者头像 李华
网站建设 2026/9/29 7:57:59

用Dify打造AI复盘助手hindsight:从后见之明到前瞻行动

做复盘这件事&#xff0c;最尴尬的场景我都经历过&#xff1a;项目结束后&#xff0c;大家坐在一起聊了两个小时&#xff0c;最后留在文档里的只是一句“下次要注意沟通”。等真正到了下一次&#xff0c;还是照样踩坑。这也是我第一次看到“hindsight”这个标题时&#xff0c;决…

作者头像 李华
网站建设 2026/9/29 7:57:44

异步加载实战指南:从懒加载到路由分包的首屏提速方案

前端圈这两年都在聊性能优化&#xff0c;什么首屏加载、白屏时间、秒开率&#xff0c;归根结底绕不开一个核心问题&#xff1a;用户拿到页面到真正能操作&#xff0c;到底等了多久。而异步加载&#xff0c;恰恰是我在项目里体会到“性价比最高、收益最明显”的一招。我最早接触…

作者头像 李华
网站建设 2026/9/29 7:57:21

基于labelme的公路隧道漏水分割:27张图小数据集训练与避坑指南

1. 这个27张图的小数据集到底能干什么先说实话&#xff0c;27张图、1个类别、labelme格式的公路隧道漏水分割数据集&#xff0c;放在今天动辄几万张的公开数据集面前&#xff0c;确实小得可怜。但小不代表没用&#xff0c;关键看你怎么用、用在哪。我在实际项目里接手过不少类似…

作者头像 李华