- UI组件
- 前端
【免费下载链接】ng-zorro-antd
Angular UI Component Library based on Ant Design
导读
本文基于 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 三个核心指令的职责
| 指令 | 类型 | 作用 |
|---|---|---|
nzFilters | NzTableFilterList | 定义筛选菜单中的筛选项列表,每项为{ text: string; value: NzSafeAny; byDefault?: boolean } |
nzFilterFn | NzTableFilterFn<T> | 筛选函数,(value: NzTableFilterValue, data: T) => boolean,决定某行数据是否被保留 |
nzFilterMultiple | boolean | 是否支持多选,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 三个核心指令的职责
| 指令 | 类型 | 作用 |
|---|---|---|
nzSortOrder | NzTableSortOrder | 当前排序状态/默认排序方向,取值为'ascend'、'descend'或null(不排序) |
nzSortFn | NzTableSortFn<T> | 排序比较函数,(a: T, b: T, sortOrder?: NzTableSortOrder) => number,返回正/负/零表示 a 与 b 的先后关系 |
nzSortDirections | NzTableSortOrder[] | 定义点击列头时依次循环切换的排序方向序列 |
类型定义见 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中还会做两件值得注意的事情:
- 自动启用排序/筛选显示:当
nzSortOrder或nzSortFn首次被设置且未显式声明nzShowSort时,会自动将nzShowSort置为true;同理,首次设置nzFilters且未声明nzShowFilter时,会自动开启筛选图标(th-addon.component.ts)。也就是说,只要绑定了排序或筛选相关属性,列头 UI 就会自动出现。 - 配置中心支持:
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
相关推荐
ng-zorro-antd Table 可控排序与筛选:用 `[nzSortOrder]` / `[nzFilters]` 编程式控制表格状态
ng zorro antd Table 可控排序与筛选:用 nzSortOrder / nzFilters 编程式控制表格状态 本篇指南聚焦 ng zorro
UI组件前端ng-zorro-antd Table 远程加载数据(Ajax)实战:服务端分页、排序与筛选
ng zorro antd Table 远程加载数据(Ajax)实战:服务端分页、排序与筛选 本文以 ng zorro antd Table 组件的 ajax
UI组件前端NG-ZORRO Table 组件完全指南:从数据渲染、排序筛选到虚拟滚动与源码级原理
NG ZORRO Table 组件完全指南:从数据渲染、排序筛选到虚拟滚动与源码级原理 nz table 是 NG ZORRO(基于 Ant Design 的
UI组件前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考