框架
版本
企业版

列筛选指南

示例

想要跳过直接看实现?查看这些示例

API

列筛选 API

列筛选指南

筛选分为 2 种类型:列筛选和全局筛选。

本指南将重点介绍列筛选,这是一种应用于单个列的访问器值的筛选器。

TanStack Table 支持客户端和手动服务端筛选。本指南将介绍如何实现和自定义这两种筛选,并帮助您确定哪种最适合您的用例。

客户端 vs 服务端筛选

如果您有大型数据集,您可能不希望将所有数据加载到客户端浏览器中进行筛选。 在这种情况下,您很可能需要实现服务端筛选、排序、分页等。

但是,正如分页指南中也讨论的那样,许多开发人员低估了客户端可以加载多少行而不会影响性能。 TanStack Table 示例通常经过测试,可以处理多达 100,000 行或更多的数据,并且在客户端筛选、排序、分页和分组方面具有不错的性能。 这不一定意味着您的应用程序能够处理那么多行,但如果您的表格最多只有几千行,您或许可以利用 TanStack Table 提供的客户端筛选、排序、分页和分组功能。

TanStack Table 可以处理数千个客户端行,并具有良好的性能。 在没有经过一些思考之前,不要排除客户端筛选、分页、排序等。

每个用例都不同,并且取决于表格的复杂性、您拥有的列数、每条数据的大小等等。 需要注意的主要瓶颈是

  1. 您的服务器是否可以在合理的时间(和成本)内查询所有数据?
  2. 提取的总大小是多少? (如果您没有很多列,这可能不会像您想象的那么糟糕。)
  3. 如果一次加载所有数据,客户端浏览器是否会占用过多内存?

如果您不确定,您可以始终从客户端筛选和分页开始,然后在未来随着数据增长切换到服务端策略。

手动服务端筛选

如果您已决定需要实现服务端筛选而不是使用内置的客户端筛选,那么下面是如何操作的。

手动服务端筛选不需要 getFilteredRowModel 表格选项。 相反,您传递给表格的 data 应该已经是筛选后的数据。 但是,如果您已传递 getFilteredRowModel 表格选项,您可以通过将 manualFiltering 选项设置为 true 来告诉表格跳过它。

jsx
const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  // getFilteredRowModel: getFilteredRowModel(), // not needed for manual server-side filtering
  manualFiltering: true,
})
const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  // getFilteredRowModel: getFilteredRowModel(), // not needed for manual server-side filtering
  manualFiltering: true,
})

注意: 当使用手动筛选时,本指南其余部分讨论的许多选项将不起作用。 当 manualFiltering 设置为 true 时,表格实例不会对传递给它的行应用任何筛选逻辑。 相反,它会假定行已预先筛选,并将您传递给它的 data 按原样使用。

客户端筛选

如果您正在使用内置的客户端筛选功能,首先您需要将 getFilteredRowModel 函数传递给表格选项。 每当表格需要筛选数据时,都会调用此函数。 您可以从 TanStack Table 导入默认的 getFilteredRowModel 函数,也可以创建自己的函数。

jsx
import { useReactTable, getFilteredRowModel } from '@tanstack/react-table'
//...
const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(), // needed for client-side filtering
})
import { useReactTable, getFilteredRowModel } from '@tanstack/react-table'
//...
const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(), // needed for client-side filtering
})

列筛选器状态

无论您使用客户端筛选还是服务端筛选,您都可以利用 TanStack Table 提供的内置列筛选器状态管理。 有许多表格和列 API 可以修改和交互筛选器状态以及检索列筛选器状态。

列筛选状态被定义为具有以下形状的对象数组

ts
interface ColumnFilter {
  id: string
  value: unknown
}
type ColumnFiltersState = ColumnFilter[]
interface ColumnFilter {
  id: string
  value: unknown
}
type ColumnFiltersState = ColumnFilter[]

由于列筛选状态是对象数组,因此您可以一次应用多个列筛选器。

访问列筛选器状态

您可以像使用任何其他表格状态一样,从表格实例访问列筛选状态,使用 table.getState() API。

jsx
const table = useReactTable({
  columns,
  data,
  //...
})

console.log(table.getState().columnFilters) // access the column filters state from the table instance
const table = useReactTable({
  columns,
  data,
  //...
})

console.log(table.getState().columnFilters) // access the column filters state from the table instance

但是,如果您需要在表格初始化之前访问列筛选状态,您可以像下面这样“控制”列筛选状态。

受控列筛选器状态

如果您需要轻松访问列筛选状态,您可以使用 state.columnFiltersonColumnFiltersChange 表格选项在您自己的状态管理中控制/管理列筛选状态。

tsx
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]) // can set initial column filter state here
//...
const table = useReactTable({
  columns,
  data,
  //...
  state: {
    columnFilters,
  },
  onColumnFiltersChange: setColumnFilters,
})
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]) // can set initial column filter state here
//...
const table = useReactTable({
  columns,
  data,
  //...
  state: {
    columnFilters,
  },
  onColumnFiltersChange: setColumnFilters,
})

初始列筛选器状态

如果您不需要在自己的状态管理或作用域中控制列筛选状态,但您仍然想要设置初始列筛选状态,则可以使用 initialState 表格选项而不是 state

jsx
const table = useReactTable({
  columns,
  data,
  //...
  initialState: {
    columnFilters: [
      {
        id: 'name',
        value: 'John', // filter the name column by 'John' by default
      },
    ],
  },
})
const table = useReactTable({
  columns,
  data,
  //...
  initialState: {
    columnFilters: [
      {
        id: 'name',
        value: 'John', // filter the name column by 'John' by default
      },
    ],
  },
})

注意:不要同时使用 initialState.columnFiltersstate.columnFilters,因为 state.columnFilters 中的初始化状态将覆盖 initialState.columnFilters

FilterFns

每列都可以有自己独特的筛选逻辑。 从 TanStack Table 提供的任何筛选函数中选择,或创建您自己的函数。

默认情况下,有 10 个内置筛选函数可供选择

  • includesString - 不区分大小写的字符串包含
  • includesStringSensitive - 区分大小写的字符串包含
  • equalsString - 不区分大小写的字符串相等
  • equalsStringSensitive - 区分大小写的字符串相等
  • arrIncludes - 数组中的项目包含
  • arrIncludesAll - 数组中包含所有项目
  • arrIncludesSome - 数组中包含某些项目
  • equals - 对象/引用相等 Object.is/===
  • weakEquals - 弱对象/引用相等 ==
  • inNumberRange - 数字范围包含

您还可以定义自己的自定义筛选函数,可以作为 filterFn 列选项,也可以使用 filterFns 表格选项作为全局筛选函数。

自定义筛选函数

注意: 这些筛选函数仅在客户端筛选期间运行。

filterFn 列选项或 filterFns 表格选项中定义自定义筛选函数时,它应具有以下签名

ts
const myCustomFilterFn: FilterFn = (row: Row, columnId: string, filterValue: any, addMeta: (meta: any) => void) => boolean
const myCustomFilterFn: FilterFn = (row: Row, columnId: string, filterValue: any, addMeta: (meta: any) => void) => boolean

每个筛选函数接收

  • 要筛选的行
  • 用于检索行值的 columnId
  • 筛选值

如果该行应包含在筛选后的行中,则应返回 true,如果应删除该行,则应返回 false

jsx
const columns = [
  {
    header: () => 'Name',
    accessorKey: 'name',
    filterFn: 'includesString', // use built-in filter function
  },
  {
    header: () => 'Age',
    accessorKey: 'age',
    filterFn: 'inNumberRange',
  },
  {
    header: () => 'Birthday',
    accessorKey: 'birthday',
    filterFn: 'myCustomFilterFn', // use custom global filter function
  },
  {
    header: () => 'Profile',
    accessorKey: 'profile',
    // use custom filter function directly
    filterFn: (row, columnId, filterValue) => {
      return // true or false based on your custom logic
    },
  }
]
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  filterFns: { // add a custom global filter function
    myCustomFilterFn: (row, columnId, filterValue) => { // defined inline here
      return // true or false based on your custom logic
    },
    startsWith: startsWithFilterFn, // defined elsewhere
  },
})
const columns = [
  {
    header: () => 'Name',
    accessorKey: 'name',
    filterFn: 'includesString', // use built-in filter function
  },
  {
    header: () => 'Age',
    accessorKey: 'age',
    filterFn: 'inNumberRange',
  },
  {
    header: () => 'Birthday',
    accessorKey: 'birthday',
    filterFn: 'myCustomFilterFn', // use custom global filter function
  },
  {
    header: () => 'Profile',
    accessorKey: 'profile',
    // use custom filter function directly
    filterFn: (row, columnId, filterValue) => {
      return // true or false based on your custom logic
    },
  }
]
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  filterFns: { // add a custom global filter function
    myCustomFilterFn: (row, columnId, filterValue) => { // defined inline here
      return // true or false based on your custom logic
    },
    startsWith: startsWithFilterFn, // defined elsewhere
  },
})
自定义筛选函数行为

您可以将一些其他属性附加到筛选函数以自定义其行为

  • filterFn.resolveFilterValue - 此可选的“附加”方法在任何给定的 filterFn 上允许筛选函数在筛选值传递给筛选函数之前转换/清理/格式化筛选值。

  • filterFn.autoRemove - 此可选的“附加”方法在任何给定的 filterFn 上,传递一个筛选值,如果筛选值应从筛选状态中删除,则应返回 true。 例如,某些布尔样式的筛选器可能希望在筛选值设置为 false 时从表格状态中删除筛选值。

tsx
const startsWithFilterFn = <TData extends MRT_RowData>(
  row: Row<TData>,
  columnId: string,
  filterValue: number | string, //resolveFilterValue will transform this to a string
) =>
  row
    .getValue<number | string>(columnId)
    .toString()
    .toLowerCase()
    .trim()
    .startsWith(filterValue); // toString, toLowerCase, and trim the filter value in `resolveFilterValue`

// remove the filter value from filter state if it is falsy (empty string in this case)
startsWithFilterFn.autoRemove = (val: any) => !val; 

// transform/sanitize/format the filter value before it is passed to the filter function
startsWithFilterFn.resolveFilterValue = (val: any) => val.toString().toLowerCase().trim(); 
const startsWithFilterFn = <TData extends MRT_RowData>(
  row: Row<TData>,
  columnId: string,
  filterValue: number | string, //resolveFilterValue will transform this to a string
) =>
  row
    .getValue<number | string>(columnId)
    .toString()
    .toLowerCase()
    .trim()
    .startsWith(filterValue); // toString, toLowerCase, and trim the filter value in `resolveFilterValue`

// remove the filter value from filter state if it is falsy (empty string in this case)
startsWithFilterFn.autoRemove = (val: any) => !val; 

// transform/sanitize/format the filter value before it is passed to the filter function
startsWithFilterFn.resolveFilterValue = (val: any) => val.toString().toLowerCase().trim(); 

自定义列筛选

您可以使用许多表格和列选项来进一步自定义列筛选行为。

禁用列筛选

默认情况下,所有列都启用列筛选。 您可以使用 enableColumnFilters 表格选项或 enableColumnFilter 列选项禁用所有列或特定列的列筛选。 您还可以通过将 enableFilters 表格选项设置为 false 来关闭列筛选和全局筛选。

禁用列的列筛选将导致 column.getCanFilter API 为该列返回 false

jsx
const columns = [
  {
    header: () => 'Id',
    accessorKey: 'id',
    enableColumnFilter: false, // disable column filtering for this column
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  enableColumnFilters: false, // disable column filtering for all columns
})
const columns = [
  {
    header: () => 'Id',
    accessorKey: 'id',
    enableColumnFilter: false, // disable column filtering for this column
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  enableColumnFilters: false, // disable column filtering for all columns
})

筛选子行 (展开)

还有一些额外的表格选项可以自定义在使用展开、分组和聚合等功能时的列筛选行为。

从叶子行筛选

默认情况下,筛选是从父行向下完成的,因此如果父行被筛选掉,其所有子行也将被筛选掉。 根据您的用例,如果您只想让用户搜索顶层行,而不是子行,这可能是所需的行为。 这也是性能最高的选项。

但是,如果您希望允许筛选和搜索子行,而不管父行是否被筛选掉,您可以将 filterFromLeafRows 表格选项设置为 true。 将此选项设置为 true 将导致筛选从叶子行向上完成,这意味着只要它们的子行或孙子行之一也包含在内,父行就会被包含在内。

jsx
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  getExpandedRowModel: getExpandedRowModel(),
  filterFromLeafRows: true, // filter and search through sub-rows
})
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  getExpandedRowModel: getExpandedRowModel(),
  filterFromLeafRows: true, // filter and search through sub-rows
})
最大叶子行筛选深度

默认情况下,筛选是针对树中的所有行完成的,无论它们是根级别的父行还是父行的子叶子行。 将 maxLeafRowFilterDepth 表格选项设置为 0 将导致筛选仅应用于根级别的父行,所有子行保持未筛选状态。 同样,将此选项设置为 1 将导致筛选仅应用于 1 级深度的子叶子行,依此类推。

如果您希望在父行通过筛选时保留父行的子行不被筛选掉,请使用 maxLeafRowFilterDepth: 0

jsx
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  getExpandedRowModel: getExpandedRowModel(),
  maxLeafRowFilterDepth: 0, // only filter root level parent rows out
})
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  getExpandedRowModel: getExpandedRowModel(),
  maxLeafRowFilterDepth: 0, // only filter root level parent rows out
})

列筛选器 API

您可以使用许多列和表格 API 与列筛选状态进行交互,并连接到您的 UI 组件。 以下是可用 API 及其最常见用例的列表

  • table.setColumnFilters - 使用新状态覆盖整个列筛选状态。

  • table.resetColumnFilters - 适用于“清除全部/重置筛选器”按钮。

  • column.getFilterValue - 适用于获取输入的默认初始筛选值,甚至直接为筛选器输入提供筛选值。

  • column.setFilterValue - 适用于将筛选器输入连接到其 onChangeonBlur 处理程序。

  • column.getCanFilter - 适用于禁用/启用筛选器输入。

  • column.getIsFiltered - 适用于显示视觉指示器,指示当前正在筛选列。

  • column.getFilterIndex - 适用于显示当前筛选器的应用顺序。

  • column.getAutoFilterFn - 在内部用于查找列的默认筛选函数(如果未指定)。

  • column.getFilterFn - 适用于显示当前正在使用的筛选模式或函数。

订阅 Bytes

您的每周 JavaScript 新闻速递。 每周一免费发送给超过 100,000 名开发者。

Bytes

无垃圾邮件。 随时取消订阅。