From 06a8283ac3076ff200265dea9a3be7fbda838fec Mon Sep 17 00:00:00 2001 From: xiaoyu2er Date: Thu, 8 May 2025 23:46:10 +0000 Subject: [PATCH] docs: update documentation translations --- docs/zh-hant/api/core/cell.md | 69 +++ docs/zh-hant/api/core/column-def.md | 108 +++++ docs/zh-hant/api/core/column.md | 78 ++++ docs/zh-hant/api/core/header-group.md | 34 ++ docs/zh-hant/api/core/header.md | 246 +++++++++++ docs/zh-hant/api/core/row.md | 110 +++++ docs/zh-hant/api/core/table.md | 386 ++++++++++++++++ docs/zh-hant/api/features/column-faceting.md | 47 ++ docs/zh-hant/api/features/column-filtering.md | 397 +++++++++++++++++ docs/zh-hant/api/features/column-ordering.md | 71 +++ docs/zh-hant/api/features/column-pinning.md | 267 +++++++++++ docs/zh-hant/api/features/column-sizing.md | 254 +++++++++++ .../zh-hant/api/features/column-visibility.md | 179 ++++++++ docs/zh-hant/api/features/expanding.md | 209 +++++++++ docs/zh-hant/api/features/filters.md | 14 + docs/zh-hant/api/features/global-faceting.md | 31 ++ docs/zh-hant/api/features/global-filtering.md | 294 +++++++++++++ docs/zh-hant/api/features/grouping.md | 354 +++++++++++++++ docs/zh-hant/api/features/pagination.md | 208 +++++++++ docs/zh-hant/api/features/pinning.md | 12 + docs/zh-hant/api/features/row-pinning.md | 141 ++++++ docs/zh-hant/api/features/row-selection.md | 231 ++++++++++ docs/zh-hant/api/features/sorting.md | 386 ++++++++++++++++ docs/zh-hant/enterprise/ag-grid.md | 44 ++ docs/zh-hant/faq.md | 167 +++++++ .../framework/angular/angular-table.md | 293 +++++++++++++ .../framework/angular/guide/table-state.md | 217 +++++++++ .../framework/lit/guide/table-state.md | 194 ++++++++ docs/zh-hant/framework/lit/lit-table.md | 64 +++ .../framework/qwik/guide/table-state.md | 179 ++++++++ docs/zh-hant/framework/qwik/qwik-table.md | 48 ++ .../framework/react/guide/table-state.md | 205 +++++++++ docs/zh-hant/framework/react/react-table.md | 20 + .../framework/solid/guide/table-state.md | 222 ++++++++++ docs/zh-hant/framework/solid/solid-table.md | 20 + .../framework/svelte/guide/table-state.md | 261 +++++++++++ docs/zh-hant/framework/svelte/svelte-table.md | 20 + .../framework/vanilla/guide/table-state.md | 6 + docs/zh-hant/framework/vanilla/table-core.md | 5 + .../framework/vue/guide/table-state.md | 249 +++++++++++ docs/zh-hant/framework/vue/vue-table.md | 48 ++ docs/zh-hant/guide/cells.md | 87 ++++ docs/zh-hant/guide/column-defs.md | 283 ++++++++++++ docs/zh-hant/guide/column-faceting.md | 90 ++++ docs/zh-hant/guide/column-filtering.md | 338 ++++++++++++++ docs/zh-hant/guide/column-ordering.md | 112 +++++ docs/zh-hant/guide/column-pinning.md | 93 ++++ docs/zh-hant/guide/column-sizing.md | 178 ++++++++ docs/zh-hant/guide/column-visibility.md | 132 ++++++ docs/zh-hant/guide/columns.md | 73 +++ docs/zh-hant/guide/custom-features.md | 286 ++++++++++++ docs/zh-hant/guide/data.md | 251 +++++++++++ docs/zh-hant/guide/expanding.md | 230 ++++++++++ docs/zh-hant/guide/features.md | 24 + docs/zh-hant/guide/filters.md | 14 + docs/zh-hant/guide/fuzzy-filtering.md | 125 ++++++ docs/zh-hant/guide/global-faceting.md | 80 ++++ docs/zh-hant/guide/global-filtering.md | 198 +++++++++ docs/zh-hant/guide/grouping.md | 148 +++++++ docs/zh-hant/guide/header-groups.md | 50 +++ docs/zh-hant/guide/headers.md | 86 ++++ docs/zh-hant/guide/migrating.md | 196 +++++++++ docs/zh-hant/guide/pagination.md | 223 ++++++++++ docs/zh-hant/guide/pinning.md | 11 + docs/zh-hant/guide/row-models.md | 123 ++++++ docs/zh-hant/guide/row-pinning.md | 21 + docs/zh-hant/guide/row-selection.md | 185 ++++++++ docs/zh-hant/guide/rows.md | 98 +++++ docs/zh-hant/guide/sorting.md | 415 ++++++++++++++++++ docs/zh-hant/guide/tables.md | 102 +++++ docs/zh-hant/guide/virtualization.md | 21 + docs/zh-hant/installation.md | 82 ++++ docs/zh-hant/introduction.md | 70 +++ docs/zh-hant/overview.md | 64 +++ docs/zh-hant/vanilla.md | 16 + 75 files changed, 10893 insertions(+) create mode 100644 docs/zh-hant/api/core/cell.md create mode 100644 docs/zh-hant/api/core/column-def.md create mode 100644 docs/zh-hant/api/core/column.md create mode 100644 docs/zh-hant/api/core/header-group.md create mode 100644 docs/zh-hant/api/core/header.md create mode 100644 docs/zh-hant/api/core/row.md create mode 100644 docs/zh-hant/api/core/table.md create mode 100644 docs/zh-hant/api/features/column-faceting.md create mode 100644 docs/zh-hant/api/features/column-filtering.md create mode 100644 docs/zh-hant/api/features/column-ordering.md create mode 100644 docs/zh-hant/api/features/column-pinning.md create mode 100644 docs/zh-hant/api/features/column-sizing.md create mode 100644 docs/zh-hant/api/features/column-visibility.md create mode 100644 docs/zh-hant/api/features/expanding.md create mode 100644 docs/zh-hant/api/features/filters.md create mode 100644 docs/zh-hant/api/features/global-faceting.md create mode 100644 docs/zh-hant/api/features/global-filtering.md create mode 100644 docs/zh-hant/api/features/grouping.md create mode 100644 docs/zh-hant/api/features/pagination.md create mode 100644 docs/zh-hant/api/features/pinning.md create mode 100644 docs/zh-hant/api/features/row-pinning.md create mode 100644 docs/zh-hant/api/features/row-selection.md create mode 100644 docs/zh-hant/api/features/sorting.md create mode 100644 docs/zh-hant/enterprise/ag-grid.md create mode 100644 docs/zh-hant/faq.md create mode 100644 docs/zh-hant/framework/angular/angular-table.md create mode 100644 docs/zh-hant/framework/angular/guide/table-state.md create mode 100644 docs/zh-hant/framework/lit/guide/table-state.md create mode 100644 docs/zh-hant/framework/lit/lit-table.md create mode 100644 docs/zh-hant/framework/qwik/guide/table-state.md create mode 100644 docs/zh-hant/framework/qwik/qwik-table.md create mode 100644 docs/zh-hant/framework/react/guide/table-state.md create mode 100644 docs/zh-hant/framework/react/react-table.md create mode 100644 docs/zh-hant/framework/solid/guide/table-state.md create mode 100644 docs/zh-hant/framework/solid/solid-table.md create mode 100644 docs/zh-hant/framework/svelte/guide/table-state.md create mode 100644 docs/zh-hant/framework/svelte/svelte-table.md create mode 100644 docs/zh-hant/framework/vanilla/guide/table-state.md create mode 100644 docs/zh-hant/framework/vanilla/table-core.md create mode 100644 docs/zh-hant/framework/vue/guide/table-state.md create mode 100644 docs/zh-hant/framework/vue/vue-table.md create mode 100644 docs/zh-hant/guide/cells.md create mode 100644 docs/zh-hant/guide/column-defs.md create mode 100644 docs/zh-hant/guide/column-faceting.md create mode 100644 docs/zh-hant/guide/column-filtering.md create mode 100644 docs/zh-hant/guide/column-ordering.md create mode 100644 docs/zh-hant/guide/column-pinning.md create mode 100644 docs/zh-hant/guide/column-sizing.md create mode 100644 docs/zh-hant/guide/column-visibility.md create mode 100644 docs/zh-hant/guide/columns.md create mode 100644 docs/zh-hant/guide/custom-features.md create mode 100644 docs/zh-hant/guide/data.md create mode 100644 docs/zh-hant/guide/expanding.md create mode 100644 docs/zh-hant/guide/features.md create mode 100644 docs/zh-hant/guide/filters.md create mode 100644 docs/zh-hant/guide/fuzzy-filtering.md create mode 100644 docs/zh-hant/guide/global-faceting.md create mode 100644 docs/zh-hant/guide/global-filtering.md create mode 100644 docs/zh-hant/guide/grouping.md create mode 100644 docs/zh-hant/guide/header-groups.md create mode 100644 docs/zh-hant/guide/headers.md create mode 100644 docs/zh-hant/guide/migrating.md create mode 100644 docs/zh-hant/guide/pagination.md create mode 100644 docs/zh-hant/guide/pinning.md create mode 100644 docs/zh-hant/guide/row-models.md create mode 100644 docs/zh-hant/guide/row-pinning.md create mode 100644 docs/zh-hant/guide/row-selection.md create mode 100644 docs/zh-hant/guide/rows.md create mode 100644 docs/zh-hant/guide/sorting.md create mode 100644 docs/zh-hant/guide/tables.md create mode 100644 docs/zh-hant/guide/virtualization.md create mode 100644 docs/zh-hant/installation.md create mode 100644 docs/zh-hant/introduction.md create mode 100644 docs/zh-hant/overview.md create mode 100644 docs/zh-hant/vanilla.md diff --git a/docs/zh-hant/api/core/cell.md b/docs/zh-hant/api/core/cell.md new file mode 100644 index 0000000000..fc6d219e54 --- /dev/null +++ b/docs/zh-hant/api/core/cell.md @@ -0,0 +1,69 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:44:14.582Z' +title: 儲存格 +--- +這是適用於所有儲存格 (cell) 的**核心**選項與 API 屬性。更多選項與 API 屬性可參閱其他[表格功能](../guide/features)。 + +## 儲存格 API (Cell API) + +所有儲存格物件皆具備以下屬性: + +### `id` + +```tsx +id: string +``` + +此儲存格在整個表格中的唯一識別碼 (ID)。 + +### `getValue` + +```tsx +getValue: () => any +``` + +透過關聯欄位 (column) 的存取器鍵 (accessor key) 或存取器函式 (accessor function) 取得儲存格的值並回傳。 + +### `renderValue` + +```tsx +renderValue: () => any +``` + +與 `getValue` 相同會回傳儲存格的值,但若找不到值時會回傳 `renderFallbackValue`。 + +### `row` + +```tsx +row: Row +``` + +此儲存格所關聯的列物件 (Row object)。 + +### `column` + +```tsx +column: Column +``` + +此儲存格所關聯的欄位物件 (Column object)。 + +### `getContext` + +```tsx +getContext: () => { + table: Table + column: Column + row: Row + cell: Cell + getValue: () => TTValue + renderValue: () => TTValue | null +} +``` + +回傳儲存格型元件 (如儲存格與聚合儲存格) 的渲染上下文 (rendering context) 或屬性 (props)。可搭配您框架的 `flexRender` 工具使用這些屬性,並依照選擇的模板進行渲染: + +```tsx +flexRender(cell.column.columnDef.cell, cell.getContext()) +``` diff --git a/docs/zh-hant/api/core/column-def.md b/docs/zh-hant/api/core/column-def.md new file mode 100644 index 0000000000..1d80d3f7cd --- /dev/null +++ b/docs/zh-hant/api/core/column-def.md @@ -0,0 +1,108 @@ +--- +source-updated-at: '2024-03-22T01:02:38.000Z' +translation-updated-at: '2025-05-08T23:44:15.675Z' +title: 欄位定義 +--- +欄位定義 (ColumnDef) 是包含以下選項的純物件: + +## 選項 + +### `id` + +```tsx +id: string +``` + +欄位的唯一識別符。 + +> 🧠 在以下情況下,欄位 ID 是選填的: +> +> - 使用物件鍵存取器 (object key accessor) 建立存取器欄位時 +> - 欄位標頭定義為字串時 + +### `accessorKey` + +```tsx +accessorKey?: string & typeof TData +``` + +從資料列物件中提取欄位值時使用的鍵名。 + +### `accessorFn` + +```tsx +accessorFn?: (originalRow: TData, index: number) => any +``` + +從每個資料列中提取欄位值時使用的存取器函式。 + +### `columns` + +```tsx +columns?: ColumnDef[] +``` + +群組欄位中包含的子欄位定義。 + +### `header` + +```tsx +header?: + | string + | ((props: { + table: Table + header: Header + column: Column + }) => unknown) +``` + +欄位顯示的標頭內容。若傳入字串,可作為欄位 ID 的預設值。若傳入函式,將會接收標頭的 props 物件,並應返回渲染後的標頭值(具體類型取決於使用的適配器)。 + +### `footer` + +```tsx +footer?: + | string + | ((props: { + table: Table + header: Header + column: Column + }) => unknown) +``` + +欄位顯示的頁尾內容。若傳入函式,將會接收頁尾的 props 物件,並應返回渲染後的頁尾值(具體類型取決於使用的適配器)。 + +### `cell` + +```tsx +cell?: + | string + | ((props: { + table: Table + row: Row + column: Column + cell: Cell + getValue: () => any + renderValue: () => any + }) => unknown) +``` + +欄位在每個資料列中顯示的儲存格內容。若傳入函式,將會接收儲存格的 props 物件,並應返回渲染後的儲存格值(具體類型取決於使用的適配器)。 + +### `meta` + +```tsx +meta?: ColumnMeta // 此介面可透過宣告合併 (declaration merging) 擴展。見下方說明! +``` + +與欄位關聯的中繼資料 (meta data)。當欄位可用時,可透過 `column.columnDef.meta` 在任何地方存取此資料。此類型對所有表格都是全域的,並可透過以下方式擴展: + +```tsx +import '@tanstack/react-table' // 或 vue、svelte、solid、qwik 等 + +declare module '@tanstack/react-table' { + interface ColumnMeta { + foo: string + } +} +``` diff --git a/docs/zh-hant/api/core/column.md b/docs/zh-hant/api/core/column.md new file mode 100644 index 0000000000..6fc6737c7e --- /dev/null +++ b/docs/zh-hant/api/core/column.md @@ -0,0 +1,78 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:44:07.088Z' +title: 欄位 +--- +這些是適用於所有欄位的**核心**選項與 API 屬性。更多選項與 API 屬性可參閱其他[表格功能](../guide/features)。 + +## 欄位 API + +所有欄位物件皆具備以下屬性: + +### `id` + +```tsx +id: string +``` + +解析後的唯一識別符,優先順序如下: + +- 來自欄位定義的手動 `id` 屬性 +- 來自欄位定義的存取器 (accessor) 鍵名 +- 來自欄位定義的標頭字串 + +### `depth` + +```tsx +depth: number +``` + +欄位的深度(若為分組欄位)相對於根欄位定義陣列。 + +### `accessorFn` + +```tsx +accessorFn?: AccessorFn +``` + +解析後的存取器函式 (accessor function),用於從每列資料中提取該欄位的值。僅在欄位定義有設定有效的存取器鍵名或函式時才會定義。 + +### `columnDef` + +```tsx +columnDef: ColumnDef +``` + +用於建立此欄位的原始欄位定義。 + +### `columns` + +```tsx +type columns = ColumnDef[] +``` + +子欄位陣列(若該欄位為群組欄位)。若非群組欄位則為空陣列。 + +### `parent` + +```tsx +parent?: Column +``` + +此欄位的父欄位。若為根欄位則為 undefined。 + +### `getFlatColumns` + +```tsx +type getFlatColumns = () => Column[] +``` + +回傳此欄位及其所有子欄位/孫欄位的扁平化陣列。 + +### `getLeafColumns` + +```tsx +type getLeafColumns = () => Column[] +``` + +回傳此欄位所有葉節點 (leaf-node) 欄位的陣列。若欄位無子欄位,則視為唯一的葉節點欄位。 diff --git a/docs/zh-hant/api/core/header-group.md b/docs/zh-hant/api/core/header-group.md new file mode 100644 index 0000000000..fed5528110 --- /dev/null +++ b/docs/zh-hant/api/core/header-group.md @@ -0,0 +1,34 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:55.956Z' +title: 標題群組 +--- +以下是所有標頭群組 (Header Group) 的**核心**選項與 API 屬性。更多選項與 API 屬性可能在其他[表格功能](../guide/features)中提供。 + +## 標頭群組 API (Header Group API) + +所有標頭群組物件皆具有以下屬性: + +### `id` + +```tsx +id: string +``` + +標頭群組的唯一識別碼。 + +### `depth` + +```tsx +depth: number +``` + +標頭群組的深度,以零為起始索引。 + +### `headers` + +```tsx +type headers = Header[] +``` + +屬於此標頭群組的[標頭 (Header)](../api/core/header) 物件陣列 diff --git a/docs/zh-hant/api/core/header.md b/docs/zh-hant/api/core/header.md new file mode 100644 index 0000000000..294739bc46 --- /dev/null +++ b/docs/zh-hant/api/core/header.md @@ -0,0 +1,246 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:44:35.771Z' +title: 標題 +--- +以下是 Header APIs 的繁體中文翻譯: + +這些是適用於所有標頭的**核心**選項與 API 屬性。更多選項與 API 屬性可能在其他[表格功能](../guide/features)中提供。 + +## 標頭 API + +所有標頭物件皆具備以下屬性: + +### `id` + +```tsx +id: string +``` + +標頭的唯一識別碼。 + +### `index` + +```tsx +index: number +``` + +標頭在所屬標頭群組中的索引位置。 + +### `depth` + +```tsx +depth: number +``` + +標頭的層級深度,以零為基底索引。 + +### `column` + +```tsx +column: Column +``` + +標頭關聯的[欄位 (Column)](../api/core/column)物件 + +### `headerGroup` + +```tsx +headerGroup: HeaderGroup +``` + +標頭關聯的[標頭群組 (HeaderGroup)](../api/core/header-group)物件 + +### `subHeaders` + +```tsx +type subHeaders = Header[] +``` + +標頭的階層式子標頭/子節點。若標頭關聯的欄位為葉節點欄位 (leaf-column),此值將為空陣列。 + +### `colSpan` + +```tsx +colSpan: number +``` + +標頭的欄位合併跨度 (col-span)。 + +### `rowSpan` + +```tsx +rowSpan: number +``` + +標頭的列合併跨度 (row-span)。 + +### `getLeafHeaders` + +```tsx +type getLeafHeaders = () => Header[] +``` + +回傳此標頭下所有階層式嵌套的葉節點標頭。 + +### `isPlaceholder` + +```tsx +isPlaceholder: boolean +``` + +標示此標頭是否為佔位標頭的布林值 + +### `placeholderId` + +```tsx +placeholderId?: string +``` + +若標頭為佔位標頭,此值將為一個不會與表格中其他標頭衝突的唯一標頭 ID + +### `getContext` + +```tsx +getContext: () => { + table: Table + header: Header + column: Column +} +``` + +回傳用於標頭、頁尾和篩選器等欄位基礎元件的渲染上下文 (或屬性)。將這些屬性與您框架的 `flexRender` 工具函式搭配使用,即可依選擇的模板進行渲染: + +```tsx +flexRender(header.column.columnDef.header, header.getContext()) +``` + +## 表格 API + +### `getHeaderGroups` + +```tsx +type getHeaderGroups = () => HeaderGroup[] +``` + +回傳表格的所有標頭群組。 + +### `getLeftHeaderGroups` + +```tsx +type getLeftHeaderGroups = () => HeaderGroup[] +``` + +若啟用固定欄位 (pinning),回傳左側固定欄位的標頭群組。 + +### `getCenterHeaderGroups` + +```tsx +type getCenterHeaderGroups = () => HeaderGroup[] +``` + +若啟用固定欄位,回傳未固定欄位的標頭群組。 + +### `getRightHeaderGroups` + +```tsx +type getRightHeaderGroups = () => HeaderGroup[] +``` + +若啟用固定欄位,回傳右側固定欄位的標頭群組。 + +### `getFooterGroups` + +```tsx +type getFooterGroups = () => HeaderGroup[] +``` + +回傳表格的所有頁尾群組。 + +### `getLeftFooterGroups` + +```tsx +type getLeftFooterGroups = () => HeaderGroup[] +``` + +若啟用固定欄位,回傳左側固定欄位的頁尾群組。 + +### `getCenterFooterGroups` + +```tsx +type getCenterFooterGroups = () => HeaderGroup[] +``` + +若啟用固定欄位,回傳未固定欄位的頁尾群組。 + +### `getRightFooterGroups` + +```tsx +type getRightFooterGroups = () => HeaderGroup[] +``` + +若啟用固定欄位,回傳右側固定欄位的頁尾群組。 + +### `getFlatHeaders` + +```tsx +type getFlatHeaders = () => Header[] +``` + +回傳表格中所有欄位的標頭,包含父標頭。 + +### `getLeftFlatHeaders` + +```tsx +type getLeftFlatHeaders = () => Header[] +``` + +若啟用固定欄位,回傳表格中所有左側固定欄位的標頭,包含父標頭。 + +### `getCenterFlatHeaders` + +```tsx +type getCenterFlatHeaders = () => Header[] +``` + +若啟用固定欄位,回傳所有未固定欄位的標頭,包含父標頭。 + +### `getRightFlatHeaders` + +```tsx +type getRightFlatHeaders = () => Header[] +``` + +若啟用固定欄位,回傳表格中所有右側固定欄位的標頭,包含父標頭。 + +### `getLeafHeaders` + +```tsx +type getLeafHeaders = () => Header[] +``` + +回傳表格中所有葉節點欄位的標頭(不包含父標頭)。 + +### `getLeftLeafHeaders` + +```tsx +type getLeftLeafHeaders = () => Header[] +``` + +若啟用固定欄位,回傳表格中所有左側固定葉節點欄位的標頭(不包含父標頭)。 + +### `getCenterLeafHeaders` + +```tsx +type getCenterLeafHeaders = () => Header[] +``` + +若啟用固定欄位,回傳所有未固定欄位的標頭(不包含父標頭)。 + +### `getRightLeafHeaders` + +```tsx +type getRightLeafHeaders = () => Header[] +``` + +若啟用固定欄位,回傳表格中所有右側固定葉節點欄位的標頭(不包含父標頭)。 diff --git a/docs/zh-hant/api/core/row.md b/docs/zh-hant/api/core/row.md new file mode 100644 index 0000000000..69bfb88a2c --- /dev/null +++ b/docs/zh-hant/api/core/row.md @@ -0,0 +1,110 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:44:06.276Z' +title: 行 +--- +這些是適用於所有列 (row) 的**核心**選項與 API 屬性。更多選項與 API 屬性可參閱其他[表格功能](../guide/features)。 + +## 列 (Row) API + +所有列物件皆具備以下屬性: + +### `id` + +```tsx +id: string +``` +透過 `options.getRowId` 選項解析出的唯一識別符。預設為列的索引(若為子列則為相對索引)。 + +### `depth` + +```tsx +depth: number +``` +列相對於根列陣列的嵌套深度(若為嵌套或分組列)。 + +### `index` + +```tsx +index: number +``` +列在其父陣列(或根資料陣列)中的索引位置。 + +### `original` + +```tsx +original: TData +``` +提供給表格的原始列物件。 + +> 🧠 若列為分組列,原始列物件將是該分組中的第一個原始物件。 + +### `parentId` + +```tsx +parentId?: string +``` +若為嵌套列,此為其父列的 id。 + +### `getValue` + +```tsx +getValue: (columnId: string) => TValue +``` +根據指定的 columnId 回傳列中對應的值。 + +### `renderValue` + +```tsx +renderValue: (columnId: string) => TValue +``` +渲染列中指定 columnId 的值,若找不到值則回傳 `renderFallbackValue`。 + +### `getUniqueValues` + +```tsx +getUniqueValues: (columnId: string) => TValue[] +``` +回傳列中指定 columnId 的唯一值陣列。 + +### `subRows` + +```tsx +type subRows = Row[] +``` +由 `options.getSubRows` 選項回傳並建立的子列陣列。 + +### `getParentRow` + +```tsx +type getParentRow = () => Row | undefined +``` +回傳此列的父列(若存在)。 + +### `getParentRows` + +```tsx +type getParentRows = () => Row[] +``` +回傳此列的所有父列,直至根列。 + +### `getLeafRows` + +```tsx +type getLeafRows = () => Row[] +``` +回傳此列的所有葉子列(不包含任何父列)。 + +### `originalSubRows` + +```tsx +originalSubRows?: TData[] +``` +由 `options.getSubRows` 選項回傳的原始子列陣列。 + +### `getAllCells` + +```tsx +type getAllCells = () => Cell[] +``` +回傳此列的所有[儲存格 (Cell)](../api/core/cell)。 diff --git a/docs/zh-hant/api/core/table.md b/docs/zh-hant/api/core/table.md new file mode 100644 index 0000000000..199d0fb533 --- /dev/null +++ b/docs/zh-hant/api/core/table.md @@ -0,0 +1,386 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:45:17.108Z' +title: 表格 +--- +## `createAngularTable` / `useReactTable` / `createSolidTable` / `useQwikTable` / `useVueTable` / `createSvelteTable` + +```tsx +type useReactTable = ( + options: TableOptions +) => Table +``` + +這些函式用於建立表格,具體使用哪一個取決於你所使用的框架適配器。 + +## 選項 + +以下是表格的**核心**選項與 API 屬性。更多選項與 API 屬性可參閱其他[表格功能](../guide/features)。 + +### `data` + +```tsx +data: TData[] +``` + +表格要顯示的資料。此陣列應與你提供給 `table.setRowType<...>` 的類型相符,但理論上可以是任何類型的陣列。通常陣列中的每個項目會是鍵/值的物件,但這並非必要條件。欄位可以透過字串/索引或函式存取器來取得此資料並回傳任何內容。 + +當 `data` 選項的參考發生變化時(透過 `Object.is` 比較),表格會重新處理資料。任何依賴核心資料模型的資料處理(如分組、排序、篩選等)也會重新執行。 + +> 🧠 請確保 `data` 選項僅在你希望表格重新處理時才變更。若每次渲染表格時都提供內聯的 `[]` 或建立新的資料陣列,將會導致大量不必要的重新處理。在小型表格中可能不易察覺,但在大型表格中會明顯影響效能。 + +### `columns` + +```tsx +type columns = ColumnDef[] +``` + +用於表格的欄位定義陣列。詳見[欄位定義指南](../../docs/guide/column-defs)以瞭解如何建立欄位定義。 + +### `defaultColumn` + +```tsx +defaultColumn?: Partial> +``` + +提供給所有欄位定義的預設選項。這對於設定預設的儲存格/表頭/表尾渲染器、排序/篩選/分組選項等非常有用。所有傳遞給 `options.columns` 的欄位定義都會與此預設定義合併,產生最終的欄位定義。 + +### `initialState` + +```tsx +initialState?: Partial< + VisibilityTableState & + ColumnOrderTableState & + ColumnPinningTableState & + FiltersTableState & + SortingTableState & + ExpandedTableState & + GroupingTableState & + ColumnSizingTableState & + PaginationTableState & + RowSelectionTableState +> +``` + +此選項用於選擇性地傳遞初始狀態給表格。當重置表格狀態時(例如透過 `options.autoResetPageIndex` 或 `table.resetRowSelection()` 等函式),會使用此狀態。大多數重置函式允許你選擇性地傳遞標誌以重置為空白/預設狀態,而非初始狀態。 + +> 🧠 表格狀態不會在此物件變更時重置,這也意味著初始狀態物件不需要保持穩定。 + +### `autoResetAll` + +```tsx +autoResetAll?: boolean +``` + +設定此選項以覆寫所有 `autoReset...` 功能選項。 + +### `meta` + +```tsx +meta?: TableMeta // 此介面可透過宣告合併擴展。見下方說明! +``` + +你可以傳遞任何物件到 `options.meta`,並在 `table` 可用的任何地方透過 `table.options.meta` 存取它。此類型對所有表格是全域的,可如下擴展: + +```tsx +declare module '@tanstack/table-core' { + interface TableMeta { + foo: string + } +} +``` + +> 🧠 將此選項視為表格的任意「上下文」。這是傳遞任意資料或函式給表格的好方法,無需將其傳遞給表格觸及的每個部分。例如,傳遞地區設定物件給表格以格式化日期、數字等,或是傳遞可更新可編輯資料的函式,如[可編輯資料範例](../framework/react/examples/editable-data)所示。 + +### `state` + +```tsx +state?: Partial< + VisibilityTableState & + ColumnOrderTableState & + ColumnPinningTableState & + FiltersTableState & + SortingTableState & + ExpandedTableState & + GroupingTableState & + ColumnSizingTableState & + PaginationTableState & + RowSelectionTableState +> +``` + +`state` 選項可用於選擇性地**控制**部分或全部表格狀態。傳遞的狀態會與內部自動管理的狀態合併並覆蓋,產生表格的最終狀態。你也可以透過 `onStateChange` 選項監聽狀態變化。 + +### `onStateChange` + +```tsx +onStateChange: (updater: Updater) => void +``` + +`onStateChange` 選項可用於選擇性地監聽表格內的狀態變化。若提供此選項,你將負責自行控制和更新表格狀態。你可以透過 `state` 選項將狀態傳回給表格。 + +### `debugAll` + +> ⚠️ 除錯功能僅在開發模式下可用。 + +```tsx +debugAll?: boolean +``` + +設定此選項為 true 以輸出所有除錯資訊到控制台。 + +### `debugTable` + +> ⚠️ 除錯功能僅在開發模式下可用。 + +```tsx +debugTable?: boolean +``` + +設定此選項為 true 以輸出表格除錯資訊到控制台。 + +### `debugHeaders` + +> ⚠️ 除錯功能僅在開發模式下可用。 + +```tsx +debugHeaders?: boolean +``` + +設定此選項為 true 以輸出表頭除錯資訊到控制台。 + +### `debugColumns` + +> ⚠️ 除錯功能僅在開發模式下可用。 + +```tsx +debugColumns?: boolean +``` + +設定此選項為 true 以輸出欄位除錯資訊到控制台。 + +### `debugRows` + +> ⚠️ 除錯功能僅在開發模式下可用。 + +```tsx +debugRows?: boolean +``` + +設定此選項為 true 以輸出列除錯資訊到控制台。 + +### `_features` + +```tsx +_features?: TableFeature[] +``` + +可新增至表格實例的額外功能陣列。 + +### `render` + +> ⚠️ 此選項僅在實作表格適配器時需要。 + +```tsx +type render = (template: Renderable, props: TProps) => any +``` + +`render` 選項為表格提供渲染器實作。此實作用於將表格的各種欄位表頭和儲存格模板轉換為使用者框架支援的結果。 + +### `mergeOptions` + +> ⚠️ 此選項僅在實作表格適配器時需要。 + +```tsx +type mergeOptions = (defaultOptions: T, options: Partial) => T +``` + +此選項用於選擇性地實作表格選項的合併。某些框架(如 solid-js)使用代理來追蹤反應性和使用情況,因此合併反應性物件需要謹慎處理。此選項將此過程的控制權反轉給適配器。 + +### `getCoreRowModel` + +```tsx +getCoreRowModel: (table: Table) => () => RowModel +``` + +此必要選項是計算並回傳表格核心列模型的函式工廠。它會**每表格呼叫一次**,並應回傳一個**新函式**,該函式會計算並回傳表格的列模型。 + +預設實作可透過任何表格適配器的 `{ getCoreRowModel }` 匯出取得。 + +### `getSubRows` + +```tsx +getSubRows?: ( + originalRow: TData, + index: number +) => undefined | TData[] +``` + +此選用函式用於存取任何給定列的子列。若使用巢狀列,你需要使用此函式從列中回傳子列物件(或 undefined)。 + +### `getRowId` + +```tsx +getRowId?: ( + originalRow: TData, + index: number, + parent?: Row +) => string +``` + +此選用函式用於為任何給定列衍生唯一 ID。若未提供,則使用列的索引(巢狀列會與其祖系的索引以 `.` 連接,例如 `index.index.index`)。若需要識別來自伺服器端操作的個別列,建議使用此函式回傳一個無論網路 IO/模糊性如何都有意義的 ID,例如 userId、taskId、資料庫 ID 欄位等。 + +## 表格 API + +以下屬性和方法可在表格物件上使用: + +### `initialState` + +```tsx +initialState: VisibilityTableState & + ColumnOrderTableState & + ColumnPinningTableState & + FiltersTableState & + SortingTableState & + ExpandedTableState & + GroupingTableState & + ColumnSizingTableState & + PaginationTableState & + RowSelectionTableState +``` + +這是表格的已解析初始狀態。 + +### `reset` + +```tsx +reset: () => void +``` + +呼叫此函式以將表格狀態重置為初始狀態。 + +### `getState` + +```tsx +getState: () => TableState +``` + +呼叫此函式以取得表格的當前狀態。建議使用此函式及其狀態,特別是在手動管理表格狀態時。這是表格內部用於所有功能和函式的完全相同狀態。 + +> 🧠 此函式回傳的狀態是自動管理的內部表格狀態與透過 `options.state` 傳遞的手動管理狀態的淺合併結果。 + +### `setState` + +```tsx +setState: (updater: Updater) => void +``` + +呼叫此函式以更新表格狀態。建議傳遞一個更新函式,形式為 `(prevState) => newState`,但也可以直接傳遞物件。 + +> 🧠 若提供 `options.onStateChange`,此函式會觸發它並傳遞新狀態。 + +### `options` + +```tsx +options: TableOptions +``` + +表格當前選項的唯讀參考。 + +> ⚠️ 此屬性通常由內部或適配器使用。可透過傳遞新選項給表格來更新。這因適配器而異。對於適配器本身,表格選項必須透過 `setOptions` 函式更新。 + +### `setOptions` + +```tsx +setOptions: (newOptions: Updater>) => void +``` + +> ⚠️ 此函式通常由適配器用來更新表格選項。可直接用於更新表格選項,但通常不建議繞過適配器的選項更新策略。 + +### `getCoreRowModel` + +```tsx +getCoreRowModel: () => { + rows: Row[], + flatRows: Row[], + rowsById: Record>, +} +``` + +回傳在套用任何處理前的核心列模型。 + +### `getRowModel` + +```tsx +getRowModel: () => { + rows: Row[], + flatRows: Row[], + rowsById: Record>, +} +``` + +回傳套用其他使用功能的所有處理後的最終模型。 + +### `getAllColumns` + +```tsx +type getAllColumns = () => Column[] +``` + +回傳表格中的所有欄位,以標準化且巢狀的階層結構呈現,與傳遞給表格的欄位定義鏡像。 + +### `getAllFlatColumns` + +```tsx +type getAllFlatColumns = () => Column[] +``` + +回傳表格中的所有欄位,扁平化為單一層級。這包括階層中的所有父欄位物件。 + +### `getAllLeafColumns` + +```tsx +type getAllLeafColumns = () => Column[] +``` + +回傳表格中的所有葉節點欄位,扁平化為單一層級。這不包括父欄位。 + +### `getColumn` + +```tsx +type getColumn = (id: string) => Column | undefined +``` + +依 ID 回傳單一欄位。 + +### `getHeaderGroups` + +```tsx +type getHeaderGroups = () => HeaderGroup[] +``` + +回傳表格的表頭群組。 + +### `getFooterGroups` + +```tsx +type getFooterGroups = () => HeaderGroup[] +``` + +回傳表格的表尾群組。 + +### `getFlatHeaders` + +```tsx +type getFlatHeaders = () => Header[] +``` + +回傳表格的扁平化 Header 物件陣列,包括父表頭。 + +### `getLeafHeaders` + +```tsx +type getLeafHeaders = () => Header[] +``` + +回傳表格的扁平化葉節點 Header 物件陣列。 diff --git a/docs/zh-hant/api/features/column-faceting.md b/docs/zh-hant/api/features/column-faceting.md new file mode 100644 index 0000000000..d7fa3e4c7a --- /dev/null +++ b/docs/zh-hant/api/features/column-faceting.md @@ -0,0 +1,47 @@ +--- +source-updated-at: '2024-03-27T23:32:27.000Z' +translation-updated-at: '2025-05-08T23:43:46.639Z' +title: 欄位面向 +id: column-faceting +--- +## 欄位 API + +### `getFacetedRowModel` + +```tsx +type getFacetedRowModel = () => RowModel +``` + +> ⚠️ 需傳入有效的 `getFacetedRowModel` 函式至 `options.facetedRowModel`。預設實作可透過匯出的 `getFacetedRowModel` 函式取得。 + +回傳已套用其他欄位篩選條件 (排除自身篩選) 的列模型 (row model)。適用於顯示分面結果計數。 + +### `getFacetedUniqueValues` + +```tsx +getFacetedUniqueValues: () => Map +``` + +> ⚠️ 需傳入有效的 `getFacetedUniqueValues` 函式至 `options.getFacetedUniqueValues`。預設實作可透過匯出的 `getFacetedUniqueValues` 函式取得。 + +此函式會**計算並回傳**從 `column.getFacetedRowModel` 衍生的唯一值及其出現次數的 `Map`。適用於顯示分面結果值。 + +### `getFacetedMinMaxValues` + +```tsx +getFacetedMinMaxValues: () => Map +``` + +> ⚠️ 需傳入有效的 `getFacetedMinMaxValues` 函式至 `options.getFacetedMinMaxValues`。預設實作可透過匯出的 `getFacetedMinMaxValues` 函式取得。 + +此函式會**計算並回傳**從 `column.getFacetedRowModel` 衍生的最小/最大值元組。適用於顯示分面結果值。 + +## 表格選項 + +### `getColumnFacetedRowModel` + +```tsx +getColumnFacetedRowModel: (columnId: string) => RowModel +``` + +回傳指定 columnId 的分面列模型 (faceted row model)。 diff --git a/docs/zh-hant/api/features/column-filtering.md b/docs/zh-hant/api/features/column-filtering.md new file mode 100644 index 0000000000..6a5e544d1c --- /dev/null +++ b/docs/zh-hant/api/features/column-filtering.md @@ -0,0 +1,397 @@ +--- +source-updated-at: '2024-03-27T23:32:27.000Z' +translation-updated-at: '2025-05-08T23:45:13.109Z' +title: 欄位過濾 +id: column-filtering +--- +## 可過濾性 (Can-Filter) + +欄位是否可進行**欄位**過濾,由以下條件決定: + +- 該欄位已定義有效的 `accessorKey`/`accessorFn` +- `column.enableColumnFilter` 未設為 `false` +- `options.enableColumnFilters` 未設為 `false` +- `options.enableFilters` 未設為 `false` + +## 狀態 (State) + +過濾狀態以以下形式儲存在表格中: + +```tsx +export interface ColumnFiltersTableState { + columnFilters: ColumnFiltersState +} + +export type ColumnFiltersState = ColumnFilter[] + +export interface ColumnFilter { + id: string + value: unknown +} +``` + +## 過濾函式 (Filter Functions) + +表格核心內建以下過濾函式: + +- `includesString` + - 不區分大小寫的字串包含檢查 +- `includesStringSensitive` + - 區分大小寫的字串包含檢查 +- `equalsString` + - 不區分大小寫的字串相等檢查 +- `equalsStringSensitive` + - 區分大小寫的字串相等檢查 +- `arrIncludes` + - 檢查項目是否包含於陣列中 +- `arrIncludesAll` + - 檢查所有項目是否包含於陣列中 +- `arrIncludesSome` + - 檢查部分項目是否包含於陣列中 +- `equals` + - 物件/參考相等檢查 `Object.is`/`===` +- `weakEquals` + - 弱物件/參考相等檢查 `==` +- `inNumberRange` + - 數值範圍包含檢查 + +每個過濾函式會接收: + +- 要過濾的列 (row) +- 用於取得列值的欄位 ID (columnId) +- 過濾值 (filter value) + +並應回傳 `true` 表示該列應包含在過濾結果中,`false` 則表示應移除。 + +以下是所有過濾函式的型別簽章: + +```tsx +export type FilterFn = { + ( + row: Row, + columnId: string, + filterValue: any, + addMeta: (meta: any) => void + ): boolean + resolveFilterValue?: TransformFilterValueFn + autoRemove?: ColumnFilterAutoRemoveTestFn + addMeta?: (meta?: any) => void +} + +export type TransformFilterValueFn = ( + value: any, + column?: Column +) => unknown + +export type ColumnFilterAutoRemoveTestFn = ( + value: any, + column?: Column +) => boolean + +export type CustomFilterFns = Record< + string, + FilterFn +> +``` + +### `filterFn.resolveFilterValue` + +這是可選的「掛載」方法,允許過濾函式在傳遞過濾值前對其進行轉換/清理/格式化。 + +### `filterFn.autoRemove` + +這是可選的「掛載」方法,會接收過濾值並預期回傳 `true` 表示該過濾值應從過濾狀態中移除。例如,某些布林型過濾器可能希望在過濾值設為 `false` 時將其從表格狀態中移除。 + +#### 使用過濾函式 (Using Filter Functions) + +過濾函式可透過以下方式在 `columnDefinition.filterFn` 中引用/定義: + +- 引用內建過濾函式的 `字串` +- 直接提供給 `columnDefinition.filterFn` 選項的函式 + +`columnDef.filterFn` 選項可用的最終過濾函式列表使用以下型別: + +```tsx +export type FilterFnOption = + | 'auto' + | BuiltInFilterFn + | FilterFn +``` + +#### 過濾元數據 (Filter Meta) + +過濾資料時常會揭露可用於後續操作的額外資訊。一個很好的例子是類似 [`match-sorter`](https://github.com/kentcdodds/match-sorter) 的排名系統,它能同時對資料進行排名、過濾和排序。雖然這類工具在單一維度的過濾+排序任務中非常實用,但表格的分散式過濾/排序架構會使其難以使用且效率低下。 + +為了讓排名/過濾/排序系統能與表格協作,`filterFn` 可選擇性地用**過濾元數據**標記結果,供後續排序/分組等操作使用。這是透過呼叫傳遞給自訂 `filterFn` 的 `addMeta` 函式來實現的。 + +以下範例使用我們自己的 `match-sorter-utils` 套件(`match-sorter` 的工具分支)來對資料進行排名、過濾和排序: + +```tsx +import { sortingFns } from '@tanstack/react-table' + +import { rankItem, compareItems } from '@tanstack/match-sorter-utils' + +const fuzzyFilter = (row, columnId, value, addMeta) => { + // 對項目進行排名 + const itemRank = rankItem(row.getValue(columnId), value) + + // 儲存排名資訊 + addMeta(itemRank) + + // 回傳該項目是否應被過濾保留/移除 + return itemRank.passed +} + +const fuzzySort = (rowA, rowB, columnId) => { + let dir = 0 + + // 僅在欄位有排名資訊時進行排序 + if (rowA.columnFiltersMeta[columnId]) { + dir = compareItems( + rowA.columnFiltersMeta[columnId]!, + rowB.columnFiltersMeta[columnId]! + ) + } + + // 當項目排名相同時,提供字母數字的後備方案 + return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir +} +``` + +## 欄位定義選項 (Column Def Options) + +### `filterFn` + +```tsx +filterFn?: FilterFn | keyof FilterFns | keyof BuiltInFilterFns +``` + +用於此欄位的過濾函式。 + +選項: + +- 引用[內建過濾函式](#filter-functions)的`字串` +- [自訂過濾函式](#filter-functions) + +### `enableColumnFilter` + +```tsx +enableColumnFilter?: boolean +``` + +啟用/停用此欄位的**欄位**過濾功能。 + +## 欄位 API (Column API) + +### `getCanFilter` + +```tsx +getCanFilter: () => boolean +``` + +回傳此欄位是否能進行**欄位**過濾。 + +### `getFilterIndex` + +```tsx +getFilterIndex: () => number +``` + +回傳此欄位過濾在表格 `state.columnFilters` 陣列中的索引(包含 `-1`)。 + +### `getIsFiltered` + +```tsx +getIsFiltered: () => boolean +``` + +回傳此欄位目前是否被過濾。 + +### `getFilterValue` + +```tsx +getFilterValue: () => unknown +``` + +回傳此欄位當前的過濾值。 + +### `setFilterValue` + +```tsx +setFilterValue: (updater: Updater) => void +``` + +設定此欄位當前過濾值的函式。可傳遞值或更新函式以進行不可變操作。 + +### `getAutoFilterFn` + +```tsx +getAutoFilterFn: (columnId: string) => FilterFn | undefined +``` + +回傳基於欄位第一個已知值自動計算的過濾函式。 + +### `getFilterFn` + +```tsx +getFilterFn: (columnId: string) => FilterFn | undefined +``` + +回傳指定欄位 ID 的過濾函式(根據配置可能是使用者定義或自動計算的)。 + +## 列 API (Row API) + +### `columnFilters` + +```tsx +columnFilters: Record +``` + +列的欄位過濾映射。此物件追蹤列是否通過/未通過特定欄位 ID 的過濾。 + +### `columnFiltersMeta` + +```tsx +columnFiltersMeta: Record +``` + +列的欄位過濾元數據映射。此物件追蹤過濾過程中可選提供的任何過濾元數據。 + +## 表格選項 (Table Options) + +### `filterFns` + +```tsx +filterFns?: Record +``` + +此選項允許定義自訂過濾函式,可透過鍵值在欄位的 `filterFn` 選項中引用。 +範例: + +```tsx +declare module '@tanstack/[adapter]-table' { + interface FilterFns { + myCustomFilter: FilterFn + } +} + +const column = columnHelper.data('key', { + filterFn: 'myCustomFilter', +}) + +const table = useReactTable({ + columns: [column], + filterFns: { + myCustomFilter: (rows, columnIds, filterValue) => { + // 回傳過濾後的列 + }, + }, +}) +``` + +### `filterFromLeafRows` + +```tsx +filterFromLeafRows?: boolean +``` + +預設情況下,過濾是從父列向下進行(因此如果父列被過濾掉,其所有子列也會被過濾掉)。將此選項設為 `true` 會使過濾從子列向上進行(這意味著只要父列的一個子列或孫列被包含,父列也會被包含)。 + +### `maxLeafRowFilterDepth` + +```tsx +maxLeafRowFilterDepth?: number +``` + +預設情況下,過濾會套用至所有列(最大深度為 100),無論它們是根層級的父列還是父列的子列。將此選項設為 `0` 會使過濾僅套用至根層級的父列,所有子列保持未過濾狀態。類似地,設為 `1` 會使過濾僅套用至一層深的子列,依此類推。 + +這在需要讓列的整個子層級結構在套用過濾後仍保持可見的情況下非常有用。 + +### `enableFilters` + +```tsx +enableFilters?: boolean +``` + +啟用/停用表格的所有過濾功能。 + +### `manualFiltering` + +```tsx +manualFiltering?: boolean +``` + +停用 `getFilteredRowModel` 用於過濾資料。這在表格需要動態支援客戶端和伺服器端過濾時可能有用。 + +### `onColumnFiltersChange` + +```tsx +onColumnFiltersChange?: OnChangeFn +``` + +若提供,當 `state.columnFilters` 變更時會呼叫此函式並傳遞 `updaterFn`。這會覆蓋預設的內部狀態管理,因此需在表格外部完全或部分保存狀態變更。 + +### `enableColumnFilters` + +```tsx +enableColumnFilters?: boolean +``` + +啟用/停用表格的**所有**欄位過濾功能。 + +### `getFilteredRowModel` + +```tsx +getFilteredRowModel?: ( + table: Table +) => () => RowModel +``` + +若提供,此函式會**每表格呼叫一次**,並應回傳**新函式**以在表格過濾時計算並回傳列模型。 + +- 對於伺服器端過濾,此函式非必要可忽略,因伺服器應已回傳過濾後的列模型。 +- 對於客戶端過濾,此函式為必需。預設實作可透過任何表格轉接器的 `{ getFilteredRowModel }` 匯出提供。 + +範例: + +```tsx +import { getFilteredRowModel } from '@tanstack/[adapter]-table' + + + getFilteredRowModel: getFilteredRowModel(), +}) +``` + +## 表格 API (Table API) + +### `setColumnFilters` + +```tsx +setColumnFilters: (updater: Updater) => void +``` + +設定或更新 `state.columnFilters` 狀態。 + +### `resetColumnFilters` + +```tsx +resetColumnFilters: (defaultState?: boolean) => void +``` + +將**columnFilters**狀態重設為 `initialState.columnFilters`,或傳遞 `true` 強制重設為預設空白狀態 `[]`。 + +### `getPreFilteredRowModel` + +```tsx +getPreFilteredRowModel: () => RowModel +``` + +回傳套用任何**欄位**過濾前的表格列模型。 + +### `getFilteredRowModel` + +```tsx +getFilteredRowModel: () => RowModel +``` + +回傳套用**欄位**過濾後的表格列模型。 diff --git a/docs/zh-hant/api/features/column-ordering.md b/docs/zh-hant/api/features/column-ordering.md new file mode 100644 index 0000000000..8aa9421d16 --- /dev/null +++ b/docs/zh-hant/api/features/column-ordering.md @@ -0,0 +1,71 @@ +--- +source-updated-at: '2024-02-18T00:06:36.000Z' +translation-updated-at: '2025-05-08T23:43:35.265Z' +title: 欄位排序 +id: column-ordering +--- +## 狀態 (State) + +欄位排序狀態 (column ordering state) 會以以下形式儲存在表格中: + +```tsx +export type ColumnOrderTableState = { + columnOrder: ColumnOrderState +} + +export type ColumnOrderState = string[] +``` + +## 表格選項 (Table Options) + +### `onColumnOrderChange` + +```tsx +onColumnOrderChange?: OnChangeFn +``` + +若提供此函式,當 `state.columnOrder` 變更時會呼叫此函式並傳入 `updaterFn`。這會覆蓋預設的內部狀態管理,因此您需要在表格外部完全或部分地持久化狀態變更。 + +## 表格 API (Table API) + +### `setColumnOrder` + +```tsx +setColumnOrder: (updater: Updater) => void +``` + +設定或更新 `state.columnOrder` 狀態。 + +### `resetColumnOrder` + +```tsx +resetColumnOrder: (defaultState?: boolean) => void +``` + +將 **columnOrder** 狀態重設為 `initialState.columnOrder`,或傳入 `true` 強制重設為預設的空狀態 `[]`。 + +## 欄位 API (Column API) + +### `getIndex` + +```tsx +getIndex: (position?: ColumnPinningPosition) => number +``` + +回傳欄位在可見欄位排序中的索引 (index)。可選擇性傳入 `position` 參數來取得欄位在表格子區段中的索引。 + +### `getIsFirstColumn` + +```tsx +getIsFirstColumn: (position?: ColumnPinningPosition) => boolean +``` + +若欄位是可見欄位排序中的第一個欄位,則回傳 `true`。可選擇性傳入 `position` 參數來檢查欄位是否為表格子區段中的第一個欄位。 + +### `getIsLastColumn` + +```tsx +getIsLastColumn: (position?: ColumnPinningPosition) => boolean +``` + +若欄位是可見欄位排序中的最後一個欄位,則回傳 `true`。可選擇性傳入 `position` 參數來檢查欄位是否為表格子區段中的最後一個欄位。 diff --git a/docs/zh-hant/api/features/column-pinning.md b/docs/zh-hant/api/features/column-pinning.md new file mode 100644 index 0000000000..d8a8c09c17 --- /dev/null +++ b/docs/zh-hant/api/features/column-pinning.md @@ -0,0 +1,267 @@ +--- +source-updated-at: '2024-03-10T17:31:15.000Z' +translation-updated-at: '2025-05-08T23:44:06.335Z' +title: 欄位固定 +id: column-pinning +--- +## 可釘選 (Can-Pin) + +欄位是否能夠被 **釘選 (pinned)** 由以下條件決定: + +- `options.enablePinning` 未設定為 `false` +- `options.enableColumnPinning` 未設定為 `false` +- `columnDefinition.enablePinning` 未設定為 `false` + +## 狀態 (State) + +釘選狀態會以以下結構儲存在表格中: + +```tsx +export type ColumnPinningPosition = false | 'left' | 'right' + +export type ColumnPinningState = { + left?: string[] + right?: string[] +} + + +export type ColumnPinningTableState = { + columnPinning: ColumnPinningState +} +``` + +## 表格選項 (Table Options) + +### `enableColumnPinning` + +```tsx +enableColumnPinning?: boolean +``` + +啟用或停用表格中所有欄位的釘選功能。 + +### `onColumnPinningChange` + +```tsx +onColumnPinningChange?: OnChangeFn +``` + +若提供此函式,當 `state.columnPinning` 變更時會呼叫此函式並傳入 `updaterFn`。這會覆蓋預設的內部狀態管理,因此您需要自行管理 `state.columnPinning` 狀態。 + +## 欄位定義選項 (Column Def Options) + +### `enablePinning` + +```tsx +enablePinning?: boolean +``` + +啟用或停用該欄位的釘選功能。 + +## 表格 API (Table API) + +### `setColumnPinning` + +```tsx +setColumnPinning: (updater: Updater) => void +``` + +設定或更新 `state.columnPinning` 狀態。 + +### `resetColumnPinning` + +```tsx +resetColumnPinning: (defaultState?: boolean) => void +``` + +將 **columnPinning** 狀態重設為 `initialState.columnPinning`,或傳入 `true` 強制重設為預設空白狀態 `{ left: [], right: [], }`。 + +### `getIsSomeColumnsPinned` + +```tsx +getIsSomeColumnsPinned: (position?: ColumnPinningPosition) => boolean +``` + +回傳是否有任何欄位被釘選。可選擇性指定僅檢查 `left` 或 `right` 位置的釘選欄位。 + +_注意:不考慮欄位可見性_ + +### `getLeftHeaderGroups` + +```tsx +getLeftHeaderGroups: () => HeaderGroup[] +``` + +回傳表格中左側釘選的標頭群組 (header groups)。 + +### `getCenterHeaderGroups` + +```tsx +getCenterHeaderGroups: () => HeaderGroup[] +``` + +回傳表格中未釘選/置中的標頭群組。 + +### `getRightHeaderGroups` + +```tsx +getRightHeaderGroups: () => HeaderGroup[] +``` + +回傳表格中右側釘選的標頭群組。 + +### `getLeftFooterGroups` + +```tsx +getLeftFooterGroups: () => HeaderGroup[] +``` + +回傳表格中左側釘選的頁尾群組 (footer groups)。 + +### `getCenterFooterGroups` + +```tsx +getCenterFooterGroups: () => HeaderGroup[] +``` + +回傳表格中未釘選/置中的頁尾群組。 + +### `getRightFooterGroups` + +```tsx +getRightFooterGroups: () => HeaderGroup[] +``` + +回傳表格中右側釘選的頁尾群組。 + +### `getLeftFlatHeaders` + +```tsx +getLeftFlatHeaders: () => Header[] +``` + +回傳表格中左側釘選標頭的扁平陣列,包含父標頭。 + +### `getCenterFlatHeaders` + +```tsx +getCenterFlatHeaders: () => Header[] +``` + +回傳表格中未釘選/置中標頭的扁平陣列,包含父標頭。 + +### `getRightFlatHeaders` + +```tsx +getRightFlatHeaders: () => Header[] +``` + +回傳表格中右側釘選標頭的扁平陣列,包含父標頭。 + +### `getLeftLeafHeaders` + +```tsx +getLeftLeafHeaders: () => Header[] +``` + +回傳表格中左側釘選葉節點標頭的扁平陣列。 + +### `getCenterLeafHeaders` + +```tsx +getCenterLeafHeaders: () => Header[] +``` + +回傳表格中未釘選/置中葉節點標頭的扁平陣列。 + +### `getRightLeafHeaders` + +```tsx +getRightLeafHeaders: () => Header[] +``` + +回傳表格中右側釘選葉節點標頭的扁平陣列。 + +### `getLeftLeafColumns` + +```tsx +getLeftLeafColumns: () => Column[] +``` + +回傳所有左側釘選的葉節點欄位。 + +### `getRightLeafColumns` + +```tsx +getRightLeafColumns: () => Column[] +``` + +回傳所有右側釘選的葉節點欄位。 + +### `getCenterLeafColumns` + +```tsx +getCenterLeafColumns: () => Column[] +``` + +回傳所有置中釘選 (未釘選) 的葉節點欄位。 + +## 欄位 API (Column API) + +### `getCanPin` + +```tsx +getCanPin: () => boolean +``` + +回傳該欄位是否可被釘選。 + +### `getPinnedIndex` + +```tsx +getPinnedIndex: () => number +``` + +回傳該欄位在所屬釘選欄位群組中的數字索引。 + +### `getIsPinned` + +```tsx +getIsPinned: () => ColumnPinningPosition +``` + +回傳該欄位的釘選位置 (`'left'`、`'right'` 或 `false`)。 + +### `pin` + +```tsx +pin: (position: ColumnPinningPosition) => void +``` + +將欄位釘選至 `'left'` 或 `'right'`,或傳入 `false` 取消釘選至置中。 + +## 列 API (Row API) + +### `getLeftVisibleCells` + +```tsx +getLeftVisibleCells: () => Cell[] +``` + +回傳該列中所有左側釘選的葉節點儲存格 (cells)。 + +### `getRightVisibleCells` + +```tsx +getRightVisibleCells: () => Cell[] +``` + +回傳該列中所有右側釘選的葉節點儲存格。 + +### `getCenterVisibleCells` + +```tsx +getCenterVisibleCells: () => Cell[] +``` + +回傳該列中所有置中釘選 (未釘選) 的葉節點儲存格。 diff --git a/docs/zh-hant/api/features/column-sizing.md b/docs/zh-hant/api/features/column-sizing.md new file mode 100644 index 0000000000..2f58215728 --- /dev/null +++ b/docs/zh-hant/api/features/column-sizing.md @@ -0,0 +1,254 @@ +--- +source-updated-at: '2024-02-18T00:06:36.000Z' +translation-updated-at: '2025-05-08T23:44:02.123Z' +title: 欄位調整大小 +id: column-sizing +--- +## 狀態 (State) + +欄位調整大小的狀態儲存在表格中,結構如下: + +```tsx +export type ColumnSizingTableState = { + columnSizing: ColumnSizing + columnSizingInfo: ColumnSizingInfoState +} + +export type ColumnSizing = Record + +export type ColumnSizingInfoState = { + startOffset: null | number + startSize: null | number + deltaOffset: null | number + deltaPercentage: null | number + isResizingColumn: false | string + columnSizingStart: [string, number][] +} +``` + +## 欄位定義選項 (Column Def Options) + +### `enableResizing` + +```tsx +enableResizing?: boolean +``` + +啟用或禁用欄位的調整大小功能。 + +### `size` + +```tsx +size?: number +``` + +欄位的預設大小。 + +### `minSize` + +```tsx +minSize?: number +``` + +欄位允許的最小大小。 + +### `maxSize` + +```tsx +maxSize?: number +``` + +欄位允許的最大大小。 + +## 欄位 API (Column API) + +### `getSize` + +```tsx +getSize: () => number +``` + +回傳欄位的目前大小。 + +### `getStart` + +```tsx +getStart: (position?: ColumnPinningPosition) => number +``` + +回傳欄位在行軸(通常為標準表格的 x 軸)上的偏移量測量值,測量所有前置欄位的大小。 + +適用於欄位的固定或絕對定位(例如 `left` 或 `transform`)。 + +### `getAfter` + +```tsx +getAfter: (position?: ColumnPinningPosition) => number +``` + +回傳欄位在行軸(通常為標準表格的 x 軸)上的偏移量測量值,測量所有後續欄位的大小。 + +適用於欄位的固定或絕對定位(例如 `right` 或 `transform`)。 + +### `getCanResize` + +```tsx +getCanResize: () => boolean +``` + +如果欄位可以調整大小,則回傳 `true`。 + +### `getIsResizing` + +```tsx +getIsResizing: () => boolean +``` + +如果欄位目前正在調整大小,則回傳 `true`。 + +### `resetSize` + +```tsx +resetSize: () => void +``` + +將欄位大小重設為初始大小。 + +## 表頭 API (Header API) + +### `getSize` + +```tsx +getSize: () => number +``` + +回傳表頭的大小,計算方式為加總所有屬於該表頭的葉欄位大小。 + +### `getStart` + +```tsx +getStart: (position?: ColumnPinningPosition) => number +``` + +回傳表頭在行軸(通常為標準表格的 x 軸)上的偏移量測量值。這實際上是所有前置表頭偏移量測量值的總和。 + +### `getResizeHandler` + +```tsx +getResizeHandler: () => (event: unknown) => void +``` + +回傳一個事件處理函數,可用於調整表頭大小。它可以作為以下事件的處理器: + +- `onMouseDown` 處理器 +- `onTouchStart` 處理器 + +拖曳和釋放事件會自動處理。 + +## 表格選項 (Table Options) + +### `enableColumnResizing` + +```tsx +enableColumnResizing?: boolean +``` + +啟用或禁用**所有欄位**的調整大小功能。 + +### `columnResizeMode` + +```tsx +columnResizeMode?: 'onChange' | 'onEnd' +``` + +決定 `columnSizing` 狀態的更新時機。`onChange` 在使用者拖曳調整大小手柄時更新狀態;`onEnd` 在使用者釋放調整大小手柄時更新狀態。 + +### `columnResizeDirection` + +```tsx +columnResizeDirection?: 'ltr' | 'rtl' +``` + +啟用或禁用從右到左的欄位調整大小支援,預設為 `'ltr'`。 + +### `onColumnSizingChange` + +```tsx +onColumnSizingChange?: OnChangeFn +``` + +此選用函數會在 `columnSizing` 狀態變更時被呼叫。如果提供此函數,您需自行管理其狀態。您可以透過 `state.columnSizing` 表格選項將此狀態傳回表格。 + +### `onColumnSizingInfoChange` + +```tsx +onColumnSizingInfoChange?: OnChangeFn +``` + +此選用函數會在 `columnSizingInfo` 狀態變更時被呼叫。如果提供此函數,您需自行管理其狀態。您可以透過 `state.columnSizingInfo` 表格選項將此狀態傳回表格。 + +## 表格 API (Table API) + +### `setColumnSizing` + +```tsx +setColumnSizing: (updater: Updater) => void +``` + +使用更新函數或值設定欄位大小狀態。如果表格選項中有傳遞 `onColumnSizingChange` 函數,則會觸發該函數;否則狀態將由表格自動管理。 + +### `setColumnSizingInfo` + +```tsx +setColumnSizingInfo: (updater: Updater) => void +``` + +使用更新函數或值設定欄位大小資訊狀態。如果表格選項中有傳遞 `onColumnSizingInfoChange` 函數,則會觸發該函數;否則狀態將由表格自動管理。 + +### `resetColumnSizing` + +```tsx +resetColumnSizing: (defaultState?: boolean) => void +``` + +將欄位大小重設為初始狀態。如果 `defaultState` 為 `true`,則會使用表格的預設狀態,而非提供給表格的初始值。 + +### `resetHeaderSizeInfo` + +```tsx +resetHeaderSizeInfo: (defaultState?: boolean) => void +``` + +將欄位大小資訊重設為初始狀態。如果 `defaultState` 為 `true`,則會使用表格的預設狀態,而非提供給表格的初始值。 + +### `getTotalSize` + +```tsx +getTotalSize: () => number +``` + +回傳表格的總大小,計算方式為加總所有葉欄位的大小。 + +### `getLeftTotalSize` + +```tsx +getLeftTotalSize: () => number +``` + +如果啟用固定欄位,回傳表格左側部分的總大小,計算方式為加總所有左側葉欄位的大小。 + +### `getCenterTotalSize` + +```tsx +getCenterTotalSize: () => number +``` + +如果啟用固定欄位,回傳表格中間部分的總大小,計算方式為加總所有未固定/中間葉欄位的大小。 + +### `getRightTotalSize` + +```tsx +getRightTotalSize: () => number +``` + +如果啟用固定欄位,回傳表格右側部分的總大小,計算方式為加總所有右側葉欄位的大小。 diff --git a/docs/zh-hant/api/features/column-visibility.md b/docs/zh-hant/api/features/column-visibility.md new file mode 100644 index 0000000000..0f22eeac68 --- /dev/null +++ b/docs/zh-hant/api/features/column-visibility.md @@ -0,0 +1,179 @@ +--- +source-updated-at: '2024-02-18T00:06:36.000Z' +translation-updated-at: '2025-05-08T23:43:42.211Z' +title: 欄位可見性 +id: column-visibility +--- +## 狀態 (State) + +欄位可見性狀態 (column visibility state) 會以以下格式儲存在表格中: + +```tsx +export type VisibilityState = Record + +export type VisibilityTableState = { + columnVisibility: VisibilityState +} +``` + +## 欄位定義選項 (Column Def Options) + +### `enableHiding` + +```tsx +enableHiding?: boolean +``` + +啟用/停用隱藏該欄位 + +## 欄位 API (Column API) + +### `getCanHide` + +```tsx +getCanHide: () => boolean +``` + +回傳該欄位是否可被隱藏 + +### `getIsVisible` + +```tsx +getIsVisible: () => boolean +``` + +回傳該欄位是否可見 + +### `toggleVisibility` + +```tsx +toggleVisibility: (value?: boolean) => void +``` + +切換欄位的可見性 + +### `getToggleVisibilityHandler` + +```tsx +getToggleVisibilityHandler: () => (event: unknown) => void +``` + +回傳一個可用於切換欄位可見性的函式。此函式可綁定至核取方塊 (checkbox) 的事件處理器。 + +## 表格選項 (Table Options) + +### `onColumnVisibilityChange` + +```tsx +onColumnVisibilityChange?: OnChangeFn +``` + +若提供此函式,當 `state.columnVisibility` 變更時會呼叫此函式並傳入 `updaterFn`。這會覆蓋預設的內部狀態管理,因此您需要在表格外部完全或部分持久化狀態變更。 + +### `enableHiding` + +```tsx +enableHiding?: boolean +``` + +啟用/停用欄位隱藏功能。 + +## 表格 API (Table API) + +### `getVisibleFlatColumns` + +```tsx +getVisibleFlatColumns: () => Column[] +``` + +回傳包含父欄位在內的可見欄位扁平陣列。 + +### `getVisibleLeafColumns` + +```tsx +getVisibleLeafColumns: () => Column[] +``` + +回傳可見的葉節點 (leaf-node) 欄位扁平陣列。 + +### `getLeftVisibleLeafColumns` + +```tsx +getLeftVisibleLeafColumns: () => Column[] +``` + +若啟用欄位釘選 (column pinning),回傳表格左側部分的可見葉節點欄位扁平陣列。 + +### `getRightVisibleLeafColumns` + +```tsx +getRightVisibleLeafColumns: () => Column[] +``` + +若啟用欄位釘選,回傳表格右側部分的可見葉節點欄位扁平陣列。 + +### `getCenterVisibleLeafColumns` + +```tsx +getCenterVisibleLeafColumns: () => Column[] +``` + +若啟用欄位釘選,回傳表格未釘選/中間部分的可見葉節點欄位扁平陣列。 + +### `setColumnVisibility` + +```tsx +setColumnVisibility: (updater: Updater) => void +``` + +透過更新函式 (updater function) 或值來更新欄位可見性狀態 + +### `resetColumnVisibility` + +```tsx +resetColumnVisibility: (defaultState?: boolean) => void +``` + +將欄位可見性狀態重設為初始狀態。若提供 `defaultState`,狀態將被重設為 `{}` + +### `toggleAllColumnsVisible` + +```tsx +toggleAllColumnsVisible: (value?: boolean) => void +``` + +切換所有欄位的可見性 + +### `getIsAllColumnsVisible` + +```tsx +getIsAllColumnsVisible: () => boolean +``` + +回傳是否所有欄位皆可見 + +### `getIsSomeColumnsVisible` + +```tsx +getIsSomeColumnsVisible: () => boolean +``` + +回傳是否部分欄位可見 + +### `getToggleAllColumnsVisibilityHandler` + +```tsx +getToggleAllColumnsVisibilityHandler: () => ((event: unknown) => void) +``` + +回傳用於切換所有欄位可見性的處理器,預期綁定至 `input[type=checkbox]` 元素。 + +## 列 API (Row API) + +### `getVisibleCells` + +```tsx +getVisibleCells: () => Cell[] +``` + +回傳該列中已考量欄位可見性的儲存格 (cell) 陣列。 diff --git a/docs/zh-hant/api/features/expanding.md b/docs/zh-hant/api/features/expanding.md new file mode 100644 index 0000000000..f3c43e5350 --- /dev/null +++ b/docs/zh-hant/api/features/expanding.md @@ -0,0 +1,209 @@ +--- +source-updated-at: '2024-02-18T00:06:36.000Z' +translation-updated-at: '2025-05-08T23:43:48.011Z' +title: 展開 +id: expanding +--- +## 狀態 (State) + +展開狀態 (expanded state) 會以下列形式儲存在表格中: + +```tsx +export type ExpandedState = true | Record + +export type ExpandedTableState = { + expanded: ExpandedState +} +``` + +## 行 (Row) API + +### `toggleExpanded` + +```tsx +toggleExpanded: (expanded?: boolean) => void +``` + +切換行的展開狀態 (若提供 `expanded` 參數則直接設定狀態)。 + +### `getIsExpanded` + +```tsx +getIsExpanded: () => boolean +``` + +回傳該行是否處於展開狀態。 + +### `getIsAllParentsExpanded` + +```tsx +getIsAllParentsExpanded: () => boolean +``` + +回傳該行的所有父行是否都已展開。 + +### `getCanExpand` + +```tsx +getCanExpand: () => boolean +``` + +回傳該行是否可以展開。 + +### `getToggleExpandedHandler` + +```tsx +getToggleExpandedHandler: () => () => void +``` + +回傳一個可用於切換該行展開狀態的函式。此函式可綁定到按鈕的事件處理器上使用。 + +## 表格選項 (Table Options) + +### `manualExpanding` + +```tsx +manualExpanding?: boolean +``` + +啟用手動行展開模式。若設為 `true`,將不會使用 `getExpandedRowModel` 來展開行,而是預期由開發者自行在資料模型中處理展開邏輯。適用於伺服器端展開 (server-side expansion) 情境。 + +### `onExpandedChange` + +```tsx +onExpandedChange?: OnChangeFn +``` + +當表格的 `expanded` 狀態變更時呼叫此函式。若提供此函式,開發者需自行管理此狀態。若要將管理後的狀態傳回表格,請使用 `tableOptions.state.expanded` 選項。 + +### `autoResetExpanded` + +```tsx +autoResetExpanded?: boolean +``` + +啟用此設定可在展開狀態變更時自動重設表格的展開狀態。 + +### `enableExpanding` + +```tsx +enableExpanding?: boolean +``` + +啟用/停用所有行的展開功能。 + +### `getExpandedRowModel` + +```tsx +getExpandedRowModel?: (table: Table) => () => RowModel +``` + +此函式負責回傳展開後的行模型 (row model)。若未提供此函式,表格將不會展開行。可使用預設匯出的 `getExpandedRowModel` 函式或自行實作。 + +### `getIsRowExpanded` + +```tsx +getIsRowExpanded?: (row: Row) => boolean +``` + +若提供此函式,可覆寫預設的「判斷行是否已展開」行為。 + +### `getRowCanExpand` + +```tsx +getRowCanExpand?: (row: Row) => boolean +``` + +若提供此函式,可覆寫預設的「判斷行是否可以展開」行為。 + +### `paginateExpandedRows` + +```tsx +paginateExpandedRows?: boolean +``` + +若設為 `true`,展開的行會與表格其他部分一起分頁 (這表示展開的行可能跨越多個分頁)。 + +若設為 `false`,展開的行不會納入分頁計算 (這表示展開的行永遠會在其父行所在的分頁中渲染,同時也意味著實際渲染的行數會超過設定的頁面大小)。 + +## 表格 API (Table API) + +### `setExpanded` + +```tsx +setExpanded: (updater: Updater) => void +``` + +透過更新函式或值來更新表格的展開狀態。 + +### `toggleAllRowsExpanded` + +```tsx +toggleAllRowsExpanded: (expanded?: boolean) => void +``` + +切換所有行的展開狀態。可選擇性提供參數來直接設定展開狀態。 + +### `resetExpanded` + +```tsx +resetExpanded: (defaultState?: boolean) => void +``` + +將表格的展開狀態重設為初始狀態。若提供 `defaultState` 參數,展開狀態會重設為 `{}`。 + +### `getCanSomeRowsExpand` + +```tsx +getCanSomeRowsExpand: () => boolean +``` + +回傳是否有任何行可被展開。 + +### `getToggleAllRowsExpandedHandler` + +```tsx +getToggleAllRowsExpandedHandler: () => (event: unknown) => void +``` + +回傳一個可用於切換所有行展開狀態的處理器。此處理器需搭配 `input[type=checkbox]` 元素使用。 + +### `getIsSomeRowsExpanded` + +```tsx +getIsSomeRowsExpanded: () => boolean +``` + +回傳是否有任何行目前處於展開狀態。 + +### `getIsAllRowsExpanded` + +```tsx +getIsAllRowsExpanded: () => boolean +``` + +回傳是否所有行目前都處於展開狀態。 + +### `getExpandedDepth` + +```tsx +getExpandedDepth: () => number +``` + +回傳已展開行的最大深度。 + +### `getExpandedRowModel` + +```tsx +getExpandedRowModel: () => RowModel +``` + +回傳套用展開處理後的行模型。 + +### `getPreExpandedRowModel` + +```tsx +getPreExpandedRowModel: () => RowModel +``` + +回傳套用展開處理前的行模型。 diff --git a/docs/zh-hant/api/features/filters.md b/docs/zh-hant/api/features/filters.md new file mode 100644 index 0000000000..e38c9403f0 --- /dev/null +++ b/docs/zh-hant/api/features/filters.md @@ -0,0 +1,14 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:09.380Z' +title: Filter APIs +id: filters +--- + + +篩選 API 文件現已拆分為多個 API 文件頁面: + +- [欄位多面篩選 (Column Faceting)](../api/features/column-faceting) +- [全域多面篩選 (Global Faceting)](../api/features/global-faceting) +- [欄位篩選 (Column Filtering)](../api/features/column-filtering) +- [全域篩選 (Global Filtering)](../api/features/global-filtering) diff --git a/docs/zh-hant/api/features/global-faceting.md b/docs/zh-hant/api/features/global-faceting.md new file mode 100644 index 0000000000..9283a34022 --- /dev/null +++ b/docs/zh-hant/api/features/global-faceting.md @@ -0,0 +1,31 @@ +--- +source-updated-at: '2024-03-27T23:32:27.000Z' +translation-updated-at: '2025-05-08T23:43:03.449Z' +title: 全域面向 +id: global-faceting +--- +## 表格 API + +### `getGlobalFacetedRowModel` + +```tsx +getGlobalFacetedRowModel: () => RowModel +``` + +回傳全域過濾器的分面式 (Faceted) 列模型。 + +### `getGlobalFacetedUniqueValues` + +```tsx +getGlobalFacetedUniqueValues: () => Map +``` + +回傳全域過濾器的分面式唯一值 (Faceted Unique Values)。 + +### `getGlobalFacetedMinMaxValues` + +```tsx +getGlobalFacetedMinMaxValues: () => [number, number] +``` + +回傳全域過濾器的分面式最小最大值 (Faceted Min/Max Values)。 diff --git a/docs/zh-hant/api/features/global-filtering.md b/docs/zh-hant/api/features/global-filtering.md new file mode 100644 index 0000000000..4686ef2c04 --- /dev/null +++ b/docs/zh-hant/api/features/global-filtering.md @@ -0,0 +1,294 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:56.137Z' +title: 全域過濾 +id: global-filtering +--- +## 全域過濾 (Global Filtering) API + +### 可過濾性 (Can-Filter) + +欄位是否能夠進行**全域**過濾取決於以下條件: + +- 該欄位已定義有效的 `accessorKey`/`accessorFn` +- 若提供 `options.getColumnCanGlobalFilter`,則需對指定欄位返回 `true`;若未提供,則預設當第一列的值為 `string` 或 `number` 類型時,該欄位可全域過濾 +- `column.enableColumnFilter` 未設為 `false` +- `options.enableColumnFilters` 未設為 `false` +- `options.enableFilters` 未設為 `false` + +### 狀態 (State) + +過濾狀態以以下形式儲存在表格中: + +```tsx +export interface GlobalFilterTableState { + globalFilter: any +} +``` + +### 過濾函式 (Filter Functions) + +全域過濾可使用與欄位過濾相同的過濾函式。詳見[欄位過濾 API](../api/features/column-filtering) 以了解過濾函式的更多資訊。 + +#### 使用過濾函式 + +可透過以下方式將過濾函式傳遞給 `options.globalFilterFn` 來使用/引用/定義: + +- 引用內建過濾函式的 `string` +- 直接提供給 `options.globalFilterFn` 選項的函式 + +`tableOptions.globalFilterFn` 選項可用的最終過濾函式列表使用以下類型: + +```tsx +export type FilterFnOption = + | 'auto' + | BuiltInFilterFn + | FilterFn +``` + +#### 過濾元數據 (Filter Meta) + +過濾數據時常會揭露關於數據的額外資訊,這些資訊可用於後續對同一數據的其他操作。此概念的一個好例子是類似 [`match-sorter`](https://github.com/kentcdodds/match-sorter) 的排名系統,它能同時對數據進行排名、過濾和排序。雖然像 `match-sorter` 這樣的工具在單一維度的過濾+排序任務中非常合理,但表格的分散式過濾/排序架構使得它們難以使用且效率低下。 + +為了讓排名/過濾/排序系統能與表格協同工作,`filterFn` 可以選擇性地用**過濾元數據**標記結果,這些數據之後可用於按需排序/分組等操作。這是透過在自訂的 `filterFn` 中調用提供的 `addMeta` 函式來實現的。 + +以下是使用我們自己的 `match-sorter-utils` 套件(`match-sorter` 的一個工具分支)來排名、過濾和排序數據的範例: + +```tsx +import { sortingFns } from '@tanstack/[adapter]-table' + +import { rankItem, compareItems } from '@tanstack/match-sorter-utils' + +const fuzzyFilter = (row, columnId, value, addMeta) => { + // 對項目進行排名 + const itemRank = rankItem(row.getValue(columnId), value) + + // 儲存排名資訊 + addMeta(itemRank) + + // 返回該項目是否應被過濾保留/排除 + return itemRank.passed +} + +const fuzzySort = (rowA, rowB, columnId) => { + let dir = 0 + + // 僅在欄位有排名資訊時進行排序 + if (rowA.columnFiltersMeta[columnId]) { + dir = compareItems( + rowA.columnFiltersMeta[columnId]!, + rowB.columnFiltersMeta[columnId]! + ) + } + + // 當項目排名相同時,提供字母數字後備方案 + return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir +} +``` + +### 欄位定義選項 (Column Def Options) + +#### `enableGlobalFilter` + +```tsx +enableGlobalFilter?: boolean +``` + +啟用/禁用此欄位的**全域**過濾功能。 + +### 欄位 API (Column API) + +#### `getCanGlobalFilter` + +```tsx +getCanGlobalFilter: () => boolean +``` + +返回該欄位是否能進行**全域**過濾。設為 `false` 可禁止在全局過濾時掃描該欄位。 + +### 行 API (Row API) + +#### `columnFiltersMeta` + +```tsx +columnFiltersMeta: Record +``` + +該行的欄位過濾元數據映射。此物件追蹤在過濾過程中可選提供的任何過濾元數據。 + +### 表格選項 (Table Options) + +#### `filterFns` + +```tsx +filterFns?: Record +``` + +此選項允許您定義自訂過濾函式,這些函式可透過其鍵在欄位的 `filterFn` 選項中引用。 +範例: + +```tsx +declare module '@tanstack/table-core' { + interface FilterFns { + myCustomFilter: FilterFn + } +} + +const column = columnHelper.data('key', { + filterFn: 'myCustomFilter', +}) + +const table = useReactTable({ + columns: [column], + filterFns: { + myCustomFilter: (rows, columnIds, filterValue) => { + // 返回過濾後的行 + }, + }, +}) +``` + +#### `filterFromLeafRows` + +```tsx +filterFromLeafRows?: boolean +``` + +預設情況下,過濾是從父行向下進行的(因此如果父行被過濾掉,其所有子行也將被過濾掉)。將此選項設為 `true` 將使過濾從葉子行向上進行(這意味著父行將被包含,只要其任一子行或孫行也被包含)。 + +#### `maxLeafRowFilterDepth` + +```tsx +maxLeafRowFilterDepth?: number +``` + +預設情況下,過濾會套用至所有行(最大深度為 100),無論它們是根級父行還是父行的子葉行。將此選項設為 `0` 將使過濾僅套用於根級父行,所有子行保持未過濾狀態。同樣,設為 `1` 將使過濾僅套用於一級深度的子葉行,依此類推。 + +這在您希望某行的整個子層次結構在應用過濾後仍可見的情況下非常有用。 + +#### `enableFilters` + +```tsx +enableFilters?: boolean +``` + +啟用/禁用表格的所有過濾功能。 + +#### `manualFiltering` + +```tsx +manualFiltering?: boolean +``` + +禁用 `getFilteredRowModel` 用於過濾數據。這在您的表格需要動態支援客戶端和伺服器端過濾時可能很有用。 + +#### `getFilteredRowModel` + +```tsx +getFilteredRowModel?: ( + table: Table +) => () => RowModel +``` + +若提供,此函式將**每表格調用一次**,並應返回一個**新函式**,該函式將在表格過濾時計算並返回行模型。 + +- 對於伺服器端過濾,此函式非必要且可忽略,因為伺服器應已返回過濾後的行模型。 +- 對於客戶端過濾,此函式是必需的。任何表格適配器的 `{ getFilteredRowModel }` 匯出都提供了預設實現。 + +範例: + +```tsx +import { getFilteredRowModel } from '@tanstack/[adapter]-table' + + getFilteredRowModel: getFilteredRowModel(), +}) +``` + +#### `globalFilterFn` + +```tsx +globalFilterFn?: FilterFn | keyof FilterFns | keyof BuiltInFilterFns +``` + +用於全域過濾的過濾函式。 + +選項: + +- 引用[內建過濾函式](#filter-functions)的 `string` +- 引用透過 `tableOptions.filterFns` 選項提供的自訂過濾函式的 `string` +- [自訂過濾函式](#filter-functions) + +#### `onGlobalFilterChange` + +```tsx +onGlobalFilterChange?: OnChangeFn +``` + +若提供,當 `state.globalFilter` 變化時,將使用 `updaterFn` 調用此函式。這將覆蓋預設的內部狀態管理,因此您需要在表格外部完全或部分持久化狀態變更。 + +#### `enableGlobalFilter` + +```tsx +enableGlobalFilter?: boolean +``` + +啟用/禁用表格的全域過濾功能。 + +#### `getColumnCanGlobalFilter` + +```tsx +getColumnCanGlobalFilter?: (column: Column) => boolean +``` + +若提供,將使用欄位調用此函式,並應返回 `true` 或 `false` 以指示該欄位是否應用於全域過濾。 +這在欄位可能包含非 `string` 或 `number` 的數據(如 `undefined`)時非常有用。 + +### 表格 API (Table API) + +#### `getPreFilteredRowModel` + +```tsx +getPreFilteredRowModel: () => RowModel +``` + +返回在套用任何**欄位**過濾前的表格行模型。 + +#### `getFilteredRowModel` + +```tsx +getFilteredRowModel: () => RowModel +``` + +返回在套用**欄位**過濾後的表格行模型。 + +#### `setGlobalFilter` + +```tsx +setGlobalFilter: (updater: Updater) => void +``` + +設定或更新 `state.globalFilter` 狀態。 + +#### `resetGlobalFilter` + +```tsx +resetGlobalFilter: (defaultState?: boolean) => void +``` + +將 **globalFilter** 狀態重置為 `initialState.globalFilter`,或傳遞 `true` 以強制重置為預設空白狀態 `undefined`。 + +#### `getGlobalAutoFilterFn` + +```tsx +getGlobalAutoFilterFn: (columnId: string) => FilterFn | undefined +``` + +目前,此函式返回內建的 `includesString` 過濾函式。在未來版本中,它可能會根據提供的數據特性返回更動態的過濾函式。 + +#### `getGlobalFilterFn` + +```tsx +getGlobalFilterFn: (columnId: string) => FilterFn | undefined +``` + +返回表格的全域過濾函式(根據配置可能是用戶定義或自動的)。 diff --git a/docs/zh-hant/api/features/grouping.md b/docs/zh-hant/api/features/grouping.md new file mode 100644 index 0000000000..0f1fc0ef03 --- /dev/null +++ b/docs/zh-hant/api/features/grouping.md @@ -0,0 +1,354 @@ +--- +source-updated-at: '2024-02-18T00:06:36.000Z' +translation-updated-at: '2025-05-08T23:43:47.458Z' +title: 分組 +id: grouping +--- +## 狀態 (State) + +群組狀態 (Grouping State) 會以下列形式儲存在表格中: + +```tsx +export type GroupingState = string[] + +export type GroupingTableState = { + grouping: GroupingState +} +``` + +## 聚合函式 (Aggregation Functions) + +表格核心內建以下聚合函式 (Aggregation Functions): + +- `sum` + - 計算一組列 (rows) 的數值總和 +- `min` + - 找出一組列的最小值 +- `max` + - 找出一組列的最大值 +- `extent` + - 找出一組列的最小值和最大值 +- `mean` + - 計算一組列的平均值 +- `median` + - 找出一組列的中位數 +- `unique` + - 找出一組列的唯一值 +- `uniqueCount` + - 計算一組列的唯一值數量 +- `count` + - 計算一組列的數量 + +每個聚合函式會接收: + +- 一個用於取得群組列葉節點值 (leaf values) 的函式 +- 一個用於取得群組列直接子節點值 (immediate-child values) 的函式 + +並應回傳一個值(通常是原始值)來建立聚合列模型 (aggregated row model)。 + +以下是所有聚合函式的型別簽章 (type signature): + +```tsx +export type AggregationFn = ( + getLeafRows: () => Row[], + getChildRows: () => Row[] +) => any +``` + +#### 使用聚合函式 (Using Aggregation Functions) + +聚合函式可以透過以下方式傳遞給 `columnDefinition.aggregationFn` 來使用/參考/定義: + +- 參考內建聚合函式的 `字串 (string)` +- 參考透過 `tableOptions.aggregationFns` 選項提供的自訂聚合函式的 `字串 (string)` +- 直接提供給 `columnDefinition.aggregationFn` 選項的函式 + +最終可用於 `columnDef.aggregationFn` 的聚合函式清單使用以下型別: + +```tsx +export type AggregationFnOption = + | 'auto' + | keyof AggregationFns + | BuiltInAggregationFn + | AggregationFn +``` + +## 列定義選項 (Column Def Options) + +### `aggregationFn` + +```tsx +aggregationFn?: AggregationFn | keyof AggregationFns | keyof BuiltInAggregationFns +``` + +用於此欄位的聚合函式。 + +選項: + +- 參考[內建聚合函式](#聚合函式-aggregation-functions)的 `字串 (string)` +- [自訂聚合函式](#聚合函式-aggregation-functions) + +### `aggregatedCell` + +```tsx +aggregatedCell?: Renderable< + { + table: Table + row: Row + column: Column + cell: Cell + getValue: () => any + renderValue: () => any + } +> +``` + +如果儲存格 (cell) 是聚合值,則顯示每個列的儲存格內容。如果傳入函式,將會傳遞一個包含儲存格上下文 (context) 的 props 物件,並應回傳適用於你的轉接器 (adapter) 的屬性型別(確切型別取決於所使用的轉接器)。 + +### `enableGrouping` + +```tsx +enableGrouping?: boolean +``` + +啟用/停用此欄位的群組功能。 + +### `getGroupingValue` + +```tsx +getGroupingValue?: (row: TData) => any +``` + +指定用於在此欄位上群組列的值。如果未指定此選項,則會使用從 `accessorKey` / `accessorFn` 衍生的值。 + +## 欄位 API (Column API) + +### `aggregationFn` + +```tsx +aggregationFn?: AggregationFnOption +``` + +此欄位解析後的聚合函式。 + +### `getCanGroup` + +```tsx +getCanGroup: () => boolean +``` + +回傳此欄位是否可以進行群組。 + +### `getIsGrouped` + +```tsx +getIsGrouped: () => boolean +``` + +回傳此欄位是否已進行群組。 + +### `getGroupedIndex` + +```tsx +getGroupedIndex: () => number +``` + +回傳此欄位在群組狀態 (Grouping State) 中的索引。 + +### `toggleGrouping` + +```tsx +toggleGrouping: () => void +``` + +切換此欄位的群組狀態。 + +### `getToggleGroupingHandler` + +```tsx +getToggleGroupingHandler: () => () => void +``` + +回傳一個用於切換此欄位群組狀態的函式。這對於傳遞給按鈕的 `onClick` 屬性非常有用。 + +### `getAutoAggregationFn` + +```tsx +getAutoAggregationFn: () => AggregationFn | undefined +``` + +回傳此欄位自動推斷的聚合函式。 + +### `getAggregationFn` + +```tsx +getAggregationFn: () => AggregationFn | undefined +``` + +回傳此欄位的聚合函式。 + +## 列 API (Row API) + +### `groupingColumnId` + +```tsx +groupingColumnId?: string +``` + +如果此列已群組,則為此列群組依據的欄位 ID。 + +### `groupingValue` + +```tsx +groupingValue?: any +``` + +如果此列已群組,則為此群組中所有列在 `groupingColumnId` 欄位上的唯一/共享值。 + +### `getIsGrouped` + +```tsx +getIsGrouped: () => boolean +``` + +回傳此列是否已進行群組。 + +### `getGroupingValue` + +```tsx +getGroupingValue: (columnId: string) => unknown +``` + +回傳任何列和欄位的群組值(包括葉節點列 (leaf rows))。 + +## 表格選項 (Table Options) + +### `aggregationFns` + +```tsx +aggregationFns?: Record +``` + +此選項允許你定義自訂聚合函式,並可透過其鍵值 (key) 在欄位的 `aggregationFn` 選項中參考。 +範例: + +```tsx +declare module '@tanstack/table-core' { + interface AggregationFns { + myCustomAggregation: AggregationFn + } +} + +const column = columnHelper.data('key', { + aggregationFn: 'myCustomAggregation', +}) + +const table = useReactTable({ + columns: [column], + aggregationFns: { + myCustomAggregation: (columnId, leafRows, childRows) => { + // 回傳聚合值 + }, + }, +}) +``` + +### `manualGrouping` + +```tsx +manualGrouping?: boolean +``` + +啟用手動群組。如果此選項設為 `true`,表格將不會自動使用 `getGroupedRowModel()` 進行列群組,而是期望你在傳遞列給表格前手動進行群組。這對於進行伺服器端群組和聚合非常有用。 + +### `onGroupingChange` + +```tsx +onGroupingChange?: OnChangeFn +``` + +如果提供此函式,當群組狀態變更時將會呼叫它,並且你將需要自行管理狀態。你可以透過 `tableOptions.state.grouping` 選項將管理後的狀態傳回表格。 + +### `enableGrouping` + +```tsx +enableGrouping?: boolean +``` + +啟用/停用所有欄位的群組功能。 + +### `getGroupedRowModel` + +```tsx +getGroupedRowModel?: (table: Table) => () => RowModel +``` + +回傳在群組完成後但未進一步處理的列模型 (row model)。 + +### `groupedColumnMode` + +```tsx +groupedColumnMode?: false | 'reorder' | 'remove' // 預設:`reorder` +``` + +群組欄位預設會自動重新排序至欄位列表的開頭。如果你希望移除它們或保持原樣,請在此設定適當的模式。 + +## 表格 API (Table API) + +### `setGrouping` + +```tsx +setGrouping: (updater: Updater) => void +``` + +設定或更新 `state.grouping` 狀態。 + +### `resetGrouping` + +```tsx +resetGrouping: (defaultState?: boolean) => void +``` + +將**群組**狀態重設為 `initialState.grouping`,或傳入 `true` 強制重設為預設空白狀態 `[]`。 + +### `getPreGroupedRowModel` + +```tsx +getPreGroupedRowModel: () => RowModel +``` + +回傳在套用任何群組前的表格列模型。 + +### `getGroupedRowModel` + +```tsx +getGroupedRowModel: () => RowModel +``` + +回傳在套用群組後的表格列模型。 + +## 儲存格 API (Cell API) + +### `getIsAggregated` + +```tsx +getIsAggregated: () => boolean +``` + +回傳此儲存格是否為聚合值。 + +### `getIsGrouped` + +```tsx +getIsGrouped: () => boolean +``` + +回傳此儲存格是否已進行群組。 + +### `getIsPlaceholder` + +```tsx +getIsPlaceholder: () => boolean +``` + +回傳此儲存格是否為佔位符 (placeholder)。 diff --git a/docs/zh-hant/api/features/pagination.md b/docs/zh-hant/api/features/pagination.md new file mode 100644 index 0000000000..38dba56789 --- /dev/null +++ b/docs/zh-hant/api/features/pagination.md @@ -0,0 +1,208 @@ +--- +source-updated-at: '2024-02-27T21:03:18.000Z' +translation-updated-at: '2025-05-08T23:43:14.429Z' +title: 分頁 +id: pagination +--- +## 分頁狀態 (Pagination State) + +分頁狀態儲存在表格中,其結構如下: + +```tsx +export type PaginationState = { + pageIndex: number + pageSize: number +} + +export type PaginationTableState = { + pagination: PaginationState +} + +export type PaginationInitialTableState = { + pagination?: Partial +} +``` + +## 表格選項 (Table Options) + +### `manualPagination` + +```tsx +manualPagination?: boolean +``` + +啟用手動分頁。若設為 `true`,表格將不會自動使用 `getPaginationRowModel()` 進行分頁,而是預期你在傳遞資料前手動完成分頁。這在實作伺服器端分頁 (server-side pagination) 和資料聚合時特別有用。 + +### `pageCount` + +```tsx +pageCount?: number +``` + +在手動控制分頁時,若已知總頁數,可透過此選項提供。若頁數未知,可設為 `-1`。或者,你也可以提供 `rowCount` 值,表格會自動計算 `pageCount`。 + +### `rowCount` + +```tsx +rowCount?: number +``` + +在手動控制分頁時,若已知總列數,可透過此選項提供。`pageCount` 會根據 `rowCount` 和 `pageSize` 自動計算。 + +### `autoResetPageIndex` + +```tsx +autoResetPageIndex?: boolean +``` + +若設為 `true`,當影響分頁的狀態變更時(例如資料更新、篩選條件變更、群組變更等),分頁會重置至第一頁。 + +> 🧠 注意:若 `manualPagination` 設為 `true`,此選項預設為 `false` + +### `onPaginationChange` + +```tsx +onPaginationChange?: OnChangeFn +``` + +若提供此函式,當分頁狀態變更時會被呼叫,此時需自行管理狀態。可透過 `tableOptions.state.pagination` 選項將管理後的狀態傳回表格。 + +### `getPaginationRowModel` + +```tsx +getPaginationRowModel?: (table: Table) => () => RowModel +``` + +回傳僅套用分頁後的列模型 (row model)。 + +預設情況下,分頁欄位會自動重新排序至欄位列表的開頭。若需移除或保持原狀,請在此設定適當模式。 + +## 表格 API (Table API) + +### `setPagination` + +```tsx +setPagination: (updater: Updater) => void +``` + +設定或更新 `state.pagination` 狀態。 + +### `resetPagination` + +```tsx +resetPagination: (defaultState?: boolean) => void +``` + +將分頁狀態重置為 `initialState.pagination`。若傳入 `true`,則會強制重置為預設空白狀態 `[]`。 + +### `setPageIndex` + +```tsx +setPageIndex: (updater: Updater) => void +``` + +使用提供的函式或值更新頁面索引 (page index)。 + +### `resetPageIndex` + +```tsx +resetPageIndex: (defaultState?: boolean) => void +``` + +將頁面索引重置為初始狀態。若 `defaultState` 為 `true`,則無論初始狀態為何,頁面索引都會重置為 `0`。 + +### `setPageSize` + +```tsx +setPageSize: (updater: Updater) => void +``` + +使用提供的函式或值更新頁面大小 (page size)。 + +### `resetPageSize` + +```tsx +resetPageSize: (defaultState?: boolean) => void +``` + +將頁面大小重置為初始狀態。若 `defaultState` 為 `true`,則無論初始狀態為何,頁面大小都會重置為 `10`。 + +### `getPageOptions` + +```tsx +getPageOptions: () => number[] +``` + +回傳當前頁面大小下的頁面選項陣列(以零為基底)。 + +### `getCanPreviousPage` + +```tsx +getCanPreviousPage: () => boolean +``` + +回傳表格是否能前往上一頁。 + +### `getCanNextPage` + +```tsx +getCanNextPage: () => boolean +``` + +回傳表格是否能前往下一頁。 + +### `previousPage` + +```tsx +previousPage: () => void +``` + +若可能,將頁面索引減一。 + +### `nextPage` + +```tsx +nextPage: () => void +``` + +若可能,將頁面索引加一。 + +### `firstPage` + +```tsx +firstPage: () => void +``` + +將頁面索引設為 `0`。 + +### `lastPage` + +```tsx +lastPage: () => void +``` + +將頁面索引設為最後一頁。 + +### `getPageCount` + +```tsx +getPageCount: () => number +``` + +回傳總頁數。若手動分頁或控制分頁狀態,此值會直接來自 `options.pageCount` 表格選項;否則會根據總列數和當前頁面大小自動計算。 + +### `getPrePaginationRowModel` + +```tsx +getPrePaginationRowModel: () => RowModel +``` + +回傳套用分頁前的表格列模型。 + +### `getPaginationRowModel` + +```tsx +getPaginationRowModel: () => RowModel +``` + +回傳套用分頁後的表格列模型。 diff --git a/docs/zh-hant/api/features/pinning.md b/docs/zh-hant/api/features/pinning.md new file mode 100644 index 0000000000..4074d7f499 --- /dev/null +++ b/docs/zh-hant/api/features/pinning.md @@ -0,0 +1,12 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:42:28.141Z' +title: Pinning APIs +id: pinning +--- + + +固定 (pinning) API 現已拆分為多個 API 頁面: + +- [欄位固定 (Column Pinning)](../api/features/column-pinning) +- [列固定 (Row Pinning)](../api/features/row-pinning) diff --git a/docs/zh-hant/api/features/row-pinning.md b/docs/zh-hant/api/features/row-pinning.md new file mode 100644 index 0000000000..022c0f0270 --- /dev/null +++ b/docs/zh-hant/api/features/row-pinning.md @@ -0,0 +1,141 @@ +--- +source-updated-at: '2024-06-30T17:39:45.000Z' +translation-updated-at: '2025-05-08T23:42:53.934Z' +title: 行固定 +id: row-pinning +--- +## 行固定 (Row Pinning) API + +## 可固定 (Can-Pin) + +某行是否可被**固定** (pinned) 由以下條件決定: + +- `options.enableRowPinning` 解析為 `true` +- `options.enablePinning` 未設定為 `false` + +## 狀態 (State) + +固定狀態會以以下形式儲存在表格中: + +```tsx +export type RowPinningPosition = false | 'top' | 'bottom' + +export type RowPinningState = { + top?: string[] + bottom?: string[] +} + +export type RowPinningRowState = { + rowPinning: RowPinningState +} +``` + +## 表格選項 (Table Options) + +### `enableRowPinning` + +```tsx +enableRowPinning?: boolean | ((row: Row) => boolean) +``` + +啟用或停用表格中所有行的固定功能。 + +### `keepPinnedRows` + +```tsx +keepPinnedRows?: boolean +``` + +當設定為 `false` 時,若固定行因過濾或分頁而被排除在表格外,則不會顯示。當設定為 `true` 時,固定行將始終可見,不受過濾或分頁影響。預設值為 `true`。 + +### `onRowPinningChange` + +```tsx +onRowPinningChange?: OnChangeFn +``` + +若提供此函數,當 `state.rowPinning` 變更時,會以 `updaterFn` 呼叫此函數。這將覆蓋預設的內部狀態管理,因此您需要從自行管理的狀態提供 `state.rowPinning`。 + +## 表格 API (Table API) + +### `setRowPinning` + +```tsx +setRowPinning: (updater: Updater) => void +``` + +設定或更新 `state.rowPinning` 狀態。 + +### `resetRowPinning` + +```tsx +resetRowPinning: (defaultState?: boolean) => void +``` + +將**行固定** (rowPinning) 狀態重置為 `initialState.rowPinning`,或可傳入 `true` 強制重置為預設空白狀態 `{}`。 + +### `getIsSomeRowsPinned` + +```tsx +getIsSomeRowsPinned: (position?: RowPinningPosition) => boolean +``` + +回傳是否有任何行被固定。可選擇性指定僅檢查 `top` 或 `bottom` 位置的固定行。 + +### `getTopRows` + +```tsx +getTopRows: () => Row[] +``` + +回傳所有固定在頂部的行。 + +### `getBottomRows` + +```tsx +getBottomRows: () => Row[] +``` + +回傳所有固定在底部的行。 + +### `getCenterRows` + +```tsx +getCenterRows: () => Row[] +``` + +回傳所有未固定在頂部或底部的行。 + +## 行 API (Row API) + +### `pin` + +```tsx +pin: (position: RowPinningPosition) => void +``` + +將行固定到 `'top'` 或 `'bottom'`,或傳入 `false` 將行取消固定至中央。 + +### `getCanPin` + +```tsx +getCanPin: () => boolean +``` + +回傳此行是否可被固定。 + +### `getIsPinned` + +```tsx +getIsPinned: () => RowPinningPosition +``` + +回傳行的固定位置 (`'top'`、`'bottom'` 或 `false`)。 + +### `getPinnedIndex` + +```tsx +getPinnedIndex: () => number +``` + +回傳行在固定行群組中的數字索引位置。 diff --git a/docs/zh-hant/api/features/row-selection.md b/docs/zh-hant/api/features/row-selection.md new file mode 100644 index 0000000000..47cf311ffd --- /dev/null +++ b/docs/zh-hant/api/features/row-selection.md @@ -0,0 +1,231 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:02.544Z' +title: 行選擇 +id: row-selection +--- +## 狀態 (State) + +列選擇狀態以下列形式儲存在表格中: + +```tsx +export type RowSelectionState = Record + +export type RowSelectionTableState = { + rowSelection: RowSelectionState +} +``` + +預設情況下,列選擇狀態使用每列的索引作為列識別符號。也可以通過向表格傳入自訂的 [getRowId](../core/table.md#getrowid) 函數,使用自訂的唯一列 ID 來追蹤列選擇狀態。 + +## 表格選項 (Table Options) + +### `enableRowSelection` + +```tsx +enableRowSelection?: boolean | ((row: Row) => boolean) +``` + +- 啟用/停用表格中所有列的列選擇功能,或 +- 一個接收列並返回是否啟用/停用該列選擇功能的函數 + +### `enableMultiRowSelection` + +```tsx +enableMultiRowSelection?: boolean | ((row: Row) => boolean) +``` + +- 啟用/停用表格中所有列的多列選擇功能,或 +- 一個接收列並返回是否啟用/停用該列的子列/孫列多列選擇功能的函數 + +### `enableSubRowSelection` + +```tsx +enableSubRowSelection?: boolean | ((row: Row) => boolean) +``` + +啟用/停用當父列被選中時自動選擇子列的功能,或一個為每列啟用/停用自動選擇子列功能的函數。 + +(需與展開或分組功能一起使用) + +### `onRowSelectionChange` + +```tsx +onRowSelectionChange?: OnChangeFn +``` + +如果提供,此函數將在 `state.rowSelection` 變更時被呼叫並傳入一個 `updaterFn`。這會覆蓋預設的內部狀態管理,因此您需要在表格外部完全或部分保存狀態變更。 + +## 表格 API (Table API) + +### `getToggleAllRowsSelectedHandler` + +```tsx +getToggleAllRowsSelectedHandler: () => (event: unknown) => void +``` + +返回一個可用於切換表格中所有列選擇狀態的處理函數。 + +### `getToggleAllPageRowsSelectedHandler` + +```tsx +getToggleAllPageRowsSelectedHandler: () => (event: unknown) => void +``` + +返回一個可用於切換當前頁面所有列選擇狀態的處理函數。 + +### `setRowSelection` + +```tsx +setRowSelection: (updater: Updater) => void +``` + +設定或更新 `state.rowSelection` 狀態。 + +### `resetRowSelection` + +```tsx +resetRowSelection: (defaultState?: boolean) => void +``` + +將 **rowSelection** 狀態重置為 `initialState.rowSelection`,或傳入 `true` 強制重置為預設空白狀態 `{}`。 + +### `getIsAllRowsSelected` + +```tsx +getIsAllRowsSelected: () => boolean +``` + +返回表格中所有列是否被選中。 + +### `getIsAllPageRowsSelected` + +```tsx +getIsAllPageRowsSelected: () => boolean +``` + +返回當前頁面所有列是否被選中。 + +### `getIsSomeRowsSelected` + +```tsx +getIsSomeRowsSelected: () => boolean +``` + +返回表格中是否有任何列被選中。 + +注意:如果所有列都被選中,則返回 `false`。 + +### `getIsSomePageRowsSelected` + +```tsx +getIsSomePageRowsSelected: () => boolean +``` + +返回當前頁面是否有任何列被選中。 + +### `toggleAllRowsSelected` + +```tsx +toggleAllRowsSelected: (value: boolean) => void +``` + +選中/取消選中表格中所有列。 + +### `toggleAllPageRowsSelected` + +```tsx +toggleAllPageRowsSelected: (value: boolean) => void +``` + +選中/取消選中當前頁面所有列。 + +### `getPreSelectedRowModel` + +```tsx +getPreSelectedRowModel: () => RowModel +``` + +### `getSelectedRowModel` + +```tsx +getSelectedRowModel: () => RowModel +``` + +### `getFilteredSelectedRowModel` + +```tsx +getFilteredSelectedRowModel: () => RowModel +``` + +### `getGroupedSelectedRowModel` + +```tsx +getGroupedSelectedRowModel: () => RowModel +``` + +## 列 API (Row API) + +### `getIsSelected` + +```tsx +getIsSelected: () => boolean +``` + +返回該列是否被選中。 + +### `getIsSomeSelected` + +```tsx +getIsSomeSelected: () => boolean +``` + +返回該列的部分子列是否被選中。 + +### `getIsAllSubRowsSelected` + +```tsx +getIsAllSubRowsSelected: () => boolean +``` + +返回該列的所有子列是否被選中。 + +### `getCanSelect` + +```tsx +getCanSelect: () => boolean +``` + +返回該列是否可以被選中。 + +### `getCanMultiSelect` + +```tsx +getCanMultiSelect: () => boolean +``` + +返回該列是否可以進行多列選擇。 + +### `getCanSelectSubRows` + +```tsx +getCanSelectSubRows: () => boolean +``` + +返回當父列被選中時,是否可以自動選擇子列。 + +### `toggleSelected` + +```tsx +toggleSelected: (value?: boolean) => void +``` + +選中/取消選中該列。 + +### `getToggleSelectedHandler` + +```tsx +getToggleSelectedHandler: () => (event: unknown) => void +``` + +返回一個可用於切換該列選擇狀態的處理函數。 diff --git a/docs/zh-hant/api/features/sorting.md b/docs/zh-hant/api/features/sorting.md new file mode 100644 index 0000000000..da74382790 --- /dev/null +++ b/docs/zh-hant/api/features/sorting.md @@ -0,0 +1,386 @@ +--- +source-updated-at: '2024-04-13T00:46:18.000Z' +translation-updated-at: '2025-05-08T23:43:44.760Z' +title: 排序 +id: sorting +--- +## 排序狀態 (Sorting State) + +排序狀態以以下形式儲存在表格中: + +```tsx +export type SortDirection = 'asc' | 'desc' + +export type ColumnSort = { + id: string + desc: boolean +} + +export type SortingState = ColumnSort[] + +export type SortingTableState = { + sorting: SortingState +} +``` + +## 排序函式 (Sorting Functions) + +表格核心內建以下排序函式: + +- `alphanumeric` + - 不區分大小寫地對混合字母數字值進行排序。速度較慢,但若字串包含需要自然排序的數字時更準確。 +- `alphanumericCaseSensitive` + - 區分大小寫地對混合字母數字值進行排序。速度較慢,但若字串包含需要自然排序的數字時更準確。 +- `text` + - 不區分大小寫地對文字/字串值進行排序。速度較快,但若字串包含需要自然排序的數字時較不準確。 +- `textCaseSensitive` + - 區分大小寫地對文字/字串值進行排序。速度較快,但若字串包含需要自然排序的數字時較不準確。 +- `datetime` + - 按時間排序,若值為 `Date` 物件時使用此函式。 +- `basic` + - 使用基礎/標準的 `a > b ? 1 : a < b ? -1 : 0` 比較進行排序。這是最快的排序函式,但可能不是最準確的。 + +每個排序函式會接收 2 行資料和一個欄位 ID,並預期透過欄位 ID 比較這兩行資料,在升冪排序時回傳 `-1`、`0` 或 `1`。以下是快速參考表: + +| 回傳值 | 升冪排序順序 | +| ------ | --------------- | +| `-1` | `a < b` | +| `0` | `a === b` | +| `1` | `a > b` | + +以下是每個排序函式的型別簽章: + +```tsx +export type SortingFn = { + (rowA: Row, rowB: Row, columnId: string): number +} +``` + +#### 使用排序函式 (Using Sorting Functions) + +可透過以下方式將排序函式傳遞給 `columnDefinition.sortingFn` 來使用/引用/定義: + +- 引用內建排序函式的 `string` +- 引用透過 `tableOptions.sortingFns` 選項提供的自訂排序函式的 `string` +- 直接提供給 `columnDefinition.sortingFn` 選項的函式 + +`columnDef.sortingFn` 可用的最終排序函式列表使用以下型別: + +```tsx +export type SortingFnOption = + | 'auto' + | SortingFns + | BuiltInSortingFns + | SortingFn +``` + +## 欄位定義選項 (Column Def Options) + +### `sortingFn` + +```tsx +sortingFn?: SortingFn | keyof SortingFns | keyof BuiltInSortingFns +``` + +用於此欄位的排序函式。 + +選項: + +- 引用[內建排序函式](#sorting-functions)的 `string` +- [自訂排序函式](#sorting-functions) + +### `sortDescFirst` + +```tsx +sortDescFirst?: boolean +``` + +設為 `true` 可讓此欄位的排序切換從降冪方向開始。 + +### `enableSorting` + +```tsx +enableSorting?: boolean +``` + +啟用/停用此欄位的排序功能。 + +### `enableMultiSort` + +```tsx +enableMultiSort?: boolean +``` + +啟用/停用此欄位的多重排序功能。 + +### `invertSorting` + +```tsx +invertSorting?: boolean +``` + +反轉此欄位的排序順序。這對於具有反向最佳/最差比例的值很有用,例如排名(第1、第2、第3)或高爾夫式計分,其中數字越小越好。 + +### `sortUndefined` + +```tsx +sortUndefined?: 'first' | 'last' | false | -1 | 1 // 預設為 1 +``` + +- `'first'` + - 未定義值會被推到列表開頭 +- `'last'` + - 未定義值會被推到列表末尾 +- `false` + - 未定義值會被視為平局,需由下一個欄位篩選器或原始索引排序(視情況而定) +- `-1` + - 未定義值會以較高優先級排序(升冪)(若為升冪排序,未定義值會出現在列表開頭) +- `1` + - 未定義值會以較低優先級排序(降冪)(若為升冪排序,未定義值會出現在列表末尾) + +> 注意:`'first'` 和 `'last'` 選項在 v8.16.0 中新增 + +## 欄位 API (Column API) + +### `getAutoSortingFn` + +```tsx +getAutoSortingFn: () => SortingFn +``` + +根據欄位值自動推斷並回傳排序函式。 + +### `getAutoSortDir` + +```tsx +getAutoSortDir: () => SortDirection +``` + +根據欄位值自動推斷並回傳排序方向。 + +### `getSortingFn` + +```tsx +getSortingFn: () => SortingFn +``` + +回傳此欄位使用的已解析排序函式。 + +### `getNextSortingOrder` + +```tsx +getNextSortingOrder: () => SortDirection | false +``` + +回傳下一個排序順序。 + +### `getCanSort` + +```tsx +getCanSort: () => boolean +``` + +回傳此欄位是否可排序。 + +### `getCanMultiSort` + +```tsx +getCanMultiSort: () => boolean +``` + +回傳此欄位是否可多重排序。 + +### `getSortIndex` + +```tsx +getSortIndex: () => number +``` + +回傳此欄位在排序狀態中的索引位置。 + +### `getIsSorted` + +```tsx +getIsSorted: () => false | SortDirection +``` + +回傳此欄位是否已排序。 + +### `getFirstSortDir` + +```tsx +getFirstSortDir: () => SortDirection +``` + +回傳排序此欄位時應使用的第一個方向。 + +### `clearSorting` + +```tsx +clearSorting: () => void +``` + +從表格的排序狀態中移除此欄位。 + +### `toggleSorting` + +```tsx +toggleSorting: (desc?: boolean, isMulti?: boolean) => void +``` + +切換此欄位的排序狀態。若提供 `desc`,則會強制排序方向為該值。若提供 `isMulti`,則會以加法方式多重排序該欄位(若已排序則切換)。 + +### `getToggleSortingHandler` + +```tsx +getToggleSortingHandler: () => undefined | ((event: unknown) => void) +``` + +回傳可用於切換此欄位排序狀態的函式。這對於將點擊處理器附加到欄位標題很有用。 + +## 表格選項 (Table Options) + +### `sortingFns` + +```tsx +sortingFns?: Record +``` + +此選項允許你定義自訂排序函式,可透過其鍵值在欄位的 `sortingFn` 選項中引用。 +範例: + +```tsx +declare module '@tanstack/table-core' { + interface SortingFns { + myCustomSorting: SortingFn + } +} + +const column = columnHelper.data('key', { + sortingFn: 'myCustomSorting', +}) + +const table = useReactTable({ + columns: [column], + sortingFns: { + myCustomSorting: (rowA: any, rowB: any, columnId: any): number => + rowA.getValue(columnId).value < rowB.getValue(columnId).value ? 1 : -1, + }, +}) +``` + +### `manualSorting` + +```tsx +manualSorting?: boolean +``` + +啟用表格的手動排序。若為 `true`,則需在將資料傳遞給表格前自行排序。這對於伺服器端排序很有用。 + +### `onSortingChange` + +```tsx +onSortingChange?: OnChangeFn +``` + +若提供,當 `state.sorting` 變更時會以 `updaterFn` 呼叫此函式。這會覆蓋預設的內部狀態管理,因此需在表格外部完全或部分保存狀態變更。 + +### `enableSorting` + +```tsx +enableSorting?: boolean +``` + +啟用/停用表格的排序功能。 + +### `enableSortingRemoval` + +```tsx +enableSortingRemoval?: boolean +``` + +啟用/停用移除表格排序的功能。 +- 若為 `true`,則排序順序會循環如下:'無' -> '降冪' -> '升冪' -> '無' -> ... +- 若為 `false`,則排序順序會循環如下:'無' -> '降冪' -> '升冪' -> '降冪' -> '升冪' -> ... + +### `enableMultiRemove` + +```tsx +enableMultiRemove?: boolean +``` + +啟用/停用移除多重排序的功能。 + +### `enableMultiSort` + +```tsx +enableMultiSort?: boolean +``` + +啟用/停用表格的多重排序功能。 + +### `sortDescFirst` + +```tsx +sortDescFirst?: boolean +``` + +若為 `true`,所有排序的首次切換狀態將預設為降冪。 + +### `getSortedRowModel` + +```tsx +getSortedRowModel?: (table: Table) => () => RowModel +``` + +此函式用於檢索已排序的行模型。若使用伺服器端排序,則不需要此函式。若要使用客戶端排序,請將從適配器匯出的 `getSortedRowModel()` 傳遞給表格,或自行實作。 + +### `maxMultiSortColCount` + +```tsx +maxMultiSortColCount?: number +``` + +設定可多重排序的欄位最大數量。 + +### `isMultiSortEvent` + +```tsx +isMultiSortEvent?: (e: unknown) => boolean +``` + +傳遞自訂函式,用於判斷是否應觸發多重排序事件。該函式會接收排序切換處理器的事件,並應在事件應觸發多重排序時回傳 `true`。 + +## 表格 API (Table API) + +### `setSorting` + +```tsx +setSorting: (updater: Updater) => void +``` + +設定或更新 `state.sorting` 狀態。 + +### `resetSorting` + +```tsx +resetSorting: (defaultState?: boolean) => void +``` + +將**排序**狀態重設為 `initialState.sorting`,或傳入 `true` 強制重設為預設空白狀態 `[]`。 + +### `getPreSortedRowModel` + +```tsx +getPreSortedRowModel: () => RowModel +``` + +回傳在套用任何排序前的表格行模型。 + +### `getSortedRowModel` + +```tsx +getSortedRowModel: () => RowModel +``` + +回傳在套用排序後的表格行模型。 diff --git a/docs/zh-hant/enterprise/ag-grid.md b/docs/zh-hant/enterprise/ag-grid.md new file mode 100644 index 0000000000..5e2c8d0bd2 --- /dev/null +++ b/docs/zh-hant/enterprise/ag-grid.md @@ -0,0 +1,44 @@ +--- +source-updated-at: '2023-12-17T15:54:46.000Z' +translation-updated-at: '2025-05-08T23:42:29.975Z' +title: AG Grid +--- +

+ + + +

+ +雖然我們非常喜愛 TanStack Table,但我們也承認它並非一個「開箱即用」、附帶客戶支援與企業級精緻度的產品。我們理解部分使用者可能仍需要這些功能!為此,我們想向您介紹 AG Grid ── 一個企業級數據表格解決方案,其豐富的功能集與強勁的效能能為您的應用程式注入強大動力。儘管 TanStack Table 也是實現數據表格的強大選項,我們相信應為使用者提供多元選擇以滿足特定需求。AG Grid 正是這樣一個選擇,我們很榮幸能為您介紹它的優勢。 + +## 為何選擇 [AG Grid](https://ag-grid.com/react-data-grid/?utm_source=reacttable&utm_campaign=githubreacttable)? + +以下是考慮在專案中使用 AG Grid 的幾項理由: + +### 完整功能集 + +AG Grid 提供廣泛的功能集,使其成為多功能且強大的數據表格解決方案。您可獲得滿足複雜企業應用需求的多樣功能,包含進階排序、篩選與分組功能,以及欄位固定、多層級表頭和樹狀資料結構支援等。AG Grid 提供您打造動態互動式數據表格所需的工具,完美契合應用程式的獨特需求。 + +### 高效能表現 + +在處理大型資料集與實現卓越效能方面,AG Grid 表現出色。它採用高度優化的渲染技術、高效資料更新與虛擬化技術,即使處理數千或數百萬筆資料列,仍能確保流暢捲動與快速回應。AG Grid 的效能優化使其成為需要高速資料操作與視覺化應用的絕佳選擇。 + +### 高度可自訂與擴充性 + +AG Grid 設計為高度可自訂與擴充,讓您能依特定需求調整表格。它提供豐富的 API 與事件系統,讓您無縫整合自訂功能。您可以定義自訂儲存格渲染器、編輯器、篩選器與聚合器來增強表格行為與外觀。AG Grid 亦支援多種主題,讓您能將表格視覺風格與應用程式設計完美搭配。 + +### 企業級需求支援 + +作為專注企業應用的解決方案,AG Grid 滿足複雜商業應用的需求。它提供企業專屬功能,如列分組、欄位固定、伺服器端列模型 (server-side row model)、主從表格 (master/detail grids) 與豐富編輯功能。AG Grid 也能與其他企業框架和函式庫良好整合,是大型專案的可靠選擇。 + +### 活躍開發與社群支援 + +AG Grid 擁有活躍的開發團隊與蓬勃的開發者社群。其團隊持續推出新功能與改進,確保產品能因應產業變化的需求。社群支援相當完善,提供論壇、文件與豐富範例,協助您充分發揮 AG Grid 的潛力。 + +## 結論 + +雖然 TanStack Table 仍是實現數據表格的強大靈活選項,我們理解不同專案有不同需求。AG Grid 提供了一個極具吸引力的企業級解決方案,可能特別符合您的需求。其完整功能集、高效能表現、自訂選項與對企業需求的重視,使 AG Grid 成為需要穩健且可擴充數據表格解決方案專案的絕佳選擇。 + +我們鼓勵您造訪 AG Grid 官網並試用其演示範例,進一步探索其功能。請記住,TanStack Table 與 AG Grid 各有獨特優勢與考量點。我們相信提供選擇給使用者,讓您能做出明智決策,為特定使用情境挑選最適合的方案。 + +前往 [AG Grid 官網](https://www.ag-grid.com)。 diff --git a/docs/zh-hant/faq.md b/docs/zh-hant/faq.md new file mode 100644 index 0000000000..1a030fc92c --- /dev/null +++ b/docs/zh-hant/faq.md @@ -0,0 +1,167 @@ +--- +source-updated-at: '2024-03-28T21:06:30.000Z' +translation-updated-at: '2025-05-08T23:40:08.738Z' +title: 常見問題 +--- +## 如何避免無限渲染迴圈? + +如果你使用 React,有一個常見的陷阱可能導致無限渲染。如果你沒有為 `columns`、`data` 或 `state` 提供穩定的參考 (stable reference),React 會在表格狀態發生任何變化時進入無限重新渲染的迴圈。 + +為什麼會這樣?這是 TanStack Table 的錯誤嗎?**不是**,這不是錯誤。*這基本上是 React 的運作方式*,妥善管理你的 columns、data 和 state 就能避免這個問題。 + +TanStack Table 的設計是當傳入表格的 `data` 或 `columns` 發生變化,或表格的任何狀態發生變化時,就會觸發重新渲染。 + +> 未能為 `columns` 或 `data` 提供穩定的參考可能導致無限重新渲染迴圈。 + +### 陷阱 1:在每次渲染時創建新的 columns 或 data + +```js +export default function MyComponent() { + //😵 錯誤:這會導致無限重新渲染迴圈,因為 `columns` 在每次渲染時都被重新定義為一個新陣列! + const columns = [ + // ... + ]; + + //😵 錯誤:這會導致無限重新渲染迴圈,因為 `data` 在每次渲染時都被重新定義為一個新陣列! + const data = [ + // ... + ]; + + //❌ Columns 和 data 在與 `useReactTable` 相同的範圍內定義且沒有穩定參考,將導致無限迴圈! + const table = useReactTable({ + columns, + data, + }); + + return ...
; +} +``` + +### 解決方案 1:使用 useMemo 或 useState 提供穩定參考 + +在 React 中,你可以透過將變數定義在元件外部/上方、使用 `useMemo` 或 `useState`,或使用第三方狀態管理庫(如 Redux 或 React Query 😉)來提供「穩定」的參考。 + +```js +//✅ 正確:在元件外部定義 columns +const columns = [ + // ... +]; + +//✅ 正確:在元件外部定義 data +const data = [ + // ... +]; + +// 通常更實際的做法是在元件內部定義 columns 和 data,因此使用 `useMemo` 或 `useState` 來提供穩定參考 +export default function MyComponent() { + //✅ 正確:這不會導致無限重新渲染迴圈,因為 `columns` 是一個穩定參考 + const columns = useMemo(() => [ + // ... + ], []); + + //✅ 正確:這不會導致無限重新渲染迴圈,因為 `data` 是一個穩定參考 + const [data, setData] = useState(() => [ + // ... + ]); + + // Columns 和 data 定義為穩定參考,不會導致無限迴圈! + const table = useReactTable({ + columns, + data, + }); + + return ...
; +} +``` + +### 陷阱 2:原地修改 columns 或 data + +即使你為初始的 `columns` 和 `data` 提供了穩定參考,如果你原地修改它們,仍然可能陷入無限迴圈。這是一個常見的陷阱,一開始可能不會注意到。即使是簡單的內聯 `data.filter()`,如果不小心使用,也可能導致無限迴圈。 + +```js +export default function MyComponent() { + //✅ 正確 + const columns = useMemo(() => [ + // ... + ], []); + + //✅ 正確(React Query 會自動為 data 提供穩定參考) + const { data, isLoading } = useQuery({ + //... + }); + + const table = useReactTable({ + columns, + //❌ 錯誤:這會導致無限重新渲染迴圈,因為 `data` 被原地修改(破壞了穩定參考) + data: data?.filter(d => d.isActive) ?? [], + }); + + return ...
; +} +``` + +### 解決方案 2:記憶化你的資料轉換 + +為了避免無限迴圈,你應該總是記憶化你的資料轉換。這可以透過 `useMemo` 或類似方法實現。 + +```js +export default function MyComponent() { + //✅ 正確 + const columns = useMemo(() => [ + // ... + ], []); + + //✅ 正確 + const { data, isLoading } = useQuery({ + //... + }); + + //✅ 正確:這不會導致無限重新渲染迴圈,因為 `filteredData` 被記憶化了 + const filteredData = useMemo(() => data?.filter(d => d.isActive) ?? [], [data]); + + const table = useReactTable({ + columns, + data: filteredData, // 穩定參考! + }); + + return ...
; +} +``` + +### React Forget + +當 React Forget 發布後,這些問題可能就會成為過去式。或者直接使用 Solid.js... 🤓 + +## 如何在資料變更時避免表格狀態自動重置? + +大多數插件使用的狀態*通常*應該在資料來源變更時重置,但有時如果你在外部過濾資料、不可變地編輯資料時查看資料,或只是對資料進行任何不希望觸發表格狀態自動重置的外部操作,你可能需要抑制這種行為。 + +對於這些情況,每個插件都提供了一種方法來禁用狀態在資料或其他依賴項變更時自動重置。通過將任何相關選項設置為 `false`,你可以阻止自動重置被觸發。 + +以下是一個基於 React 的範例,展示如何在編輯表格的 `data` 來源時阻止所有狀態像平常那樣變更: + +```js +const [data, setData] = React.useState([]) +const skipPageResetRef = React.useRef() + +const updateData = newData => { + // 當使用此函數更新資料時,設置一個標記 + // 以禁用所有自動重置 + skipPageResetRef.current = true + + setData(newData) +} + +React.useEffect(() => { + // 在表格更新後,總是移除標記 + skipPageResetRef.current = false +}) + +useReactTable({ + ... + autoResetPageIndex: !skipPageResetRef.current, + autoResetExpanded: !skipPageResetRef.current, +}) +``` + +現在,當我們更新資料時,上述表格狀態將不會自動重置! diff --git a/docs/zh-hant/framework/angular/angular-table.md b/docs/zh-hant/framework/angular/angular-table.md new file mode 100644 index 0000000000..1dd400436c --- /dev/null +++ b/docs/zh-hant/framework/angular/angular-table.md @@ -0,0 +1,293 @@ +--- +source-updated-at: '2025-01-20T06:07:15.000Z' +translation-updated-at: '2025-05-08T23:43:28.754Z' +title: Angular 表格適配器 +--- +`@tanstack/angular-table` 適配器是核心表格邏輯的封裝層,其主要職責是以「Angular 訊號 (signals)」的方式管理狀態,並提供型別定義以及單元格/表頭/表尾模板的渲染實現。 + +## 導出項目 + +`@tanstack/angular-table` 重新導出了 `@tanstack/table-core` 的所有 API 以及以下內容: + +### `createAngularTable` + +接受一個回傳表格選項的函數或計算值,並回傳一個表格實例。 + +```ts +import {createAngularTable} from '@tanstack/angular-table' + +export class AppComponent { + data = signal([]) + + table = createAngularTable(() => ({ + data: this.data(), + columns: defaultColumns, + getCoreRowModel: getCoreRowModel(), + })) +} + +// ...在模板中渲染你的表格 +``` + +### `FlexRender` + +一個 Angular 結構型指令,用於渲染帶有動態值的單元格/表頭/表尾模板。 + +FlexRender 支援 Angular 支援的任何內容類型: + +- 字串或透過 `innerHTML` 傳遞的 HTML 字串 +- [TemplateRef](https://angular.dev/api/core/TemplateRef) +- 包裝成 `FlexRenderComponent` 的[元件 (Component)](https://angular.dev/api/core/Component) + +你可以直接使用 `cell.renderValue` 或 `cell.getValue` API 來渲染表格單元格。然而,這些 API 僅會輸出原始單元格值(來自存取函數)。若你使用 `cell: () => any` 欄位定義選項,則需要使用適配器提供的 `FlexRenderDirective`。 + +單元格欄位定義是**響應式 (reactive)** 的,並在**注入上下文 (injection context)** 中執行,因此你可以注入服務或使用訊號來自動修改渲染內容。 + +#### 範例 + +```ts +@Component({ + imports: [FlexRenderDirective], + //... +}) +class YourComponent {} +``` + +```angular-html + +@for (row of table.getRowModel().rows; track row.id) { + + @for (cell of row.getVisibleCells(); track cell.id) { + + + + {{ cell }} + +
+
+ + } + +} + +``` + +#### 渲染元件 + +若要將元件渲染到特定欄位的表頭/單元格/表尾,你可以傳遞一個 `FlexRenderComponent` 實例,其中包含你的 `ComponentType`,並可設定輸入參數、輸出事件和自訂注入器。 + +```ts +import {flexRenderComponent} from "./flex-render-component"; +import {ChangeDetectionStrategy, input, output} from "@angular/core"; + +@Component({ + template: ` + ... + `, + standalone: true, + changeDetectionStrategy: ChangeDetectionStrategy.OnPush, + host: { + '(click)': 'clickEvent.emit($event)' + } +}) +class CustomCell { + readonly content = input.required(); + readonly cellType = input(); + + // 點擊事件輸出 + readonly clickEvent = output(); +} + +class AppComponent { + columns: ColumnDef[] = [ + { + id: 'custom-cell', + header: () => { + const translateService = inject(TranslateService); + return translateService.translate('...'); + }, + cell: (context) => { + return flexRenderComponent( + MyCustomComponent, + { + injector, // 可選注入器 + inputs: { + // 必填輸入項(因使用 `input.required()`) + content: context.row.original.rowProperty, + // cellType? - 可選輸入項 + }, + outputs: { + clickEvent: () => { + // 執行某些操作 + } + } + } + ) + }, + }, + ] +} +``` + +底層實作使用了 [ViewContainerRef#createComponent](https://angular.dev/api/core/ViewContainerRef#createComponent) API。因此,你應使用 `@Input` 裝飾器或 input/model 訊號來宣告自訂輸入項。 + +你仍可透過 `injectFlexRenderContext` 函數存取表格單元格上下文,該函數會根據傳遞給 `FlexRenderDirective` 的 props 回傳對應的上下文值。 + +```ts +@Component({ + // ... +}) +class CustomCellComponent { + // 單元格元件的上下文 + readonly context = injectFlexRenderContext>(); + // 表頭/表尾元件的上下文 + readonly context = injectFlexRenderContext>(); +} +``` + +或者,你可以透過將元件類型傳遞給對應的欄位定義,將元件渲染到特定欄位的表頭、單元格或表尾。這些欄位定義會連同 `context` 一起提供給 `flexRender` 指令。 + +```ts +class AppComponent { + columns: ColumnDef[] = [ + { + id: 'select', + header: () => TableHeadSelectionComponent, + cell: () => TableRowSelectionComponent, + }, + ] +} +``` + +```angular-html + + {{ headerCell }} + +``` + +`flexRender` 指令提供的 `context` 屬性可被你的元件存取。你可以明確定義元件所需的上下文屬性。在此範例中,提供給 flexRender 的上下文類型為 `HeaderContext`。輸入訊號 `table` 是 `HeaderContext` 的屬性之一,與 `column` 和 `header` 屬性一起定義,供元件使用。若需要存取其他上下文屬性,可自由使用。請注意,此方式僅支援輸入訊號。 + +```angular-ts +@Component({ + template: ` + + `, + // ... +}) +export class TableHeadSelectionComponent { + //column = input.required>() + //header = input.required>() + table = input.required>() +} +``` + +#### 渲染 TemplateRef + +若要將 `TemplateRef` 渲染到特定欄位的表頭/單元格/表尾,你可以將 `TemplateRef` 傳遞給欄位定義。 + +你可以透過 `$implicit` 屬性存取 `TemplateRef` 的資料,該屬性的值基於 `flexRender` 的 `props` 欄位傳遞的內容。 + +在多數情況下,每個 `TemplateRef` 會根據單元格類型以下列方式渲染 `$implicit` 上下文: + +- 表頭:`HeaderContext` +- 單元格:`CellContext` +- 表尾:`HeaderContext` + +```angular-html + + + {{ cell }} + +
+
+ + + + +``` + +完整範例: + +```angular-ts +import type { + CellContext, + ColumnDef, + HeaderContext, +} from '@tanstack/angular-table' +import {Component, TemplateRef, viewChild} from '@angular/core' + +@Component({ + template: ` + + @for (row of table.getRowModel().rows; track row.id) { + + @for (cell of row.getVisibleCells(); track cell.id) { + + + + {{ cell }} + +
+
+ + } + + } + + + + {{ context.getValue() }} + + + {{ context.getValue() }} + + `, +}) +class AppComponent { + customHeader = + viewChild.required }>>( + 'customHeader' + ) + customCell = + viewChild.required }>>( + 'customCell' + ) + + columns: ColumnDef[] = [ + { + id: 'customCell', + header: () => this.customHeader(), + cell: () => this.customCell(), + }, + ] +} +``` diff --git a/docs/zh-hant/framework/angular/guide/table-state.md b/docs/zh-hant/framework/angular/guide/table-state.md new file mode 100644 index 0000000000..65935075c3 --- /dev/null +++ b/docs/zh-hant/framework/angular/guide/table-state.md @@ -0,0 +1,217 @@ +--- +source-updated-at: '2024-07-27T18:15:45.000Z' +translation-updated-at: '2025-05-08T23:45:35.053Z' +title: 表格狀態 +--- +## 表格狀態 (Angular) 指南 + +TanStack Table 的核心是**框架無關 (framework agnostic)** 的,這意味著無論您使用哪種框架,其 API 都是相同的。根據您使用的框架,提供了適配器 (adapters) 來簡化與表格核心的互動。請參閱適配器選單以查看可用的適配器。 + +### 存取表格狀態 + +您無需特別設置任何內容即可讓表格狀態正常工作。如果您沒有向 `state`、`initialState` 或任何 `on[State]Change` 表格選項傳入任何內容,表格將在內部管理自己的狀態。您可以透過使用 `table.getState()` 表格實例 API 來存取此內部狀態的任何部分。 + +```ts +table = createAngularTable(() => ({ + columns: this.columns, + data: this.data(), + //... +})) + +someHandler() { + console.log(this.table.getState()) //存取整個內部狀態 + console.log(this.table.getState().rowSelection) //僅存取行選擇狀態 +} +``` + +### 自訂初始狀態 + +如果您只需要為某些狀態自訂其初始預設值,您仍然不需要自行管理任何狀態。您只需在表格實例的 `initialState` 選項中設置值即可。 + +```jsx +table = createAngularTable(() => ({ + columns: this.columns, + data: this.data(), + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降序排序 + } + ] + }, + //... +})) +``` + +> **注意**:每個特定狀態只能在 `initialState` 或 `state` 中指定,但不能同時在兩者中指定。如果您將特定狀態值同時傳入 `initialState` 和 `state`,則 `state` 中的初始化狀態將覆蓋 `initialState` 中的任何對應值。 + +### 受控狀態 + +如果您需要在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 讓您可以輕鬆地在自己的狀態管理系統中控制和管理的任何或所有表格狀態。您可以透過將自己的狀態和狀態管理函數傳入 `state` 和 `on[State]Change` 表格選項來實現這一點。 + +#### 個別受控狀態 + +您可以僅控制您需要輕鬆存取的狀態。如果不需要,您**不必**控制所有表格狀態。建議根據具體情況僅控制您需要的狀態。 + +為了控制特定狀態,您需要將對應的 `state` 值和 `on[State]Change` 函數傳入表格實例。 + +讓我們以「手動」伺服器端資料獲取情境中的篩選、排序和分頁為例。您可以將篩選、排序和分頁狀態儲存在自己的狀態管理中,但如果您的 API 不關心這些值,則可以忽略其他狀態,如欄位順序、欄位可見性等。 + +```ts +import {signal} from '@angular/core'; +import {SortingState, ColumnFiltersState, PaginationState} from '@tanstack/angular-table' +import {toObservable} from "@angular/core/rxjs-interop"; +import {combineLatest, switchMap} from 'rxjs'; + +class TableComponent { + readonly columnFilters = signal([]) //無預設篩選 + readonly sorting = signal([ + { + id: 'age', + desc: true, //預設按年齡降序排序 + } + ]) + readonly pagination = signal({ + pageIndex: 0, + pageSize: 15 + }) + + //使用我們受控的狀態值來獲取資料 + readonly data$ = combineLatest({ + filters: toObservable(this.columnFilters), + sorting: toObservable(this.sorting), + pagination: toObservable(this.pagination) + }).pipe( + switchMap(({filters, sorting, pagination}) => fetchData(filters, sorting, pagination)) + ) + readonly data = toSignal(this.data$); + + readonly table = createAngularTable(() => ({ + columns: this.columns, + data: this.data(), + //... + state: { + columnFilters: this.columnFilters(), //將受控狀態傳回表格(覆蓋內部狀態) + sorting: this.sorting(), + pagination: this.pagination(), + }, + onColumnFiltersChange: updater => { //將 columnFilters 狀態提升到我們自己的狀態管理 + updater instanceof Function + ? this.columnFilters.update(updater) + : this.columnFilters.set(updater) + }, + onSortingChange: updater => { + updater instanceof Function + ? this.sorting.update(updater) + : this.sorting.set(updater) + }, + onPaginationChange: updater => { + updater instanceof Function + ? this.pagination.update(updater) + : this.pagination.set(updater) + }, + })) +} + +//... +``` + +#### 完全受控狀態 + +或者,您可以使用 `onStateChange` 表格選項來控制整個表格狀態。它會將整個表格狀態提升到您自己的狀態管理系統中。請小心使用此方法,因為您可能會發現將一些頻繁變化的狀態值(如 `columnSizingInfo` 狀態)提升到元件樹中可能會導致性能問題。 + +可能需要一些技巧來實現這一點。如果您使用 `onStateChange` 表格選項,則 `state` 的初始值必須填充您想要使用的所有相關狀態值。您可以手動輸入所有初始狀態值,或以特殊方式使用建構函數,如下所示。 + +```ts + + +class TableComponent { + // 建立一個空的表格狀態,稍後我們會覆蓋它 + readonly state = signal({} as TableState); + + // 使用預設狀態值建立表格實例 + readonly table = createAngularTable(() => ({ + columns: this.columns, + data: this.data(), + // 我們完全受控的狀態覆蓋了內部狀態 + state: this.state(), + onStateChange: updater => { + // 任何狀態變更都會被推送到我們自己的狀態管理 + this.state.set( + updater instanceof Function ? updater(this.state()) : updater + ) + } + })) + + constructor() { + // 設定初始表格狀態 + this.state.set({ + // 使用表格實例中的所有預設狀態值填充初始狀態 + ...this.table.initialState, + pagination: { + pageIndex: 0, + pageSize: 15, // 可選自訂初始分頁狀態 + }, + }) + } +} +``` + +### 狀態變更回呼 + +到目前為止,我們已經看到 `on[State]Change` 和 `onStateChange` 表格選項可以將表格狀態變更「提升」到我們自己的狀態管理中。然而,關於使用這些選項,有幾點您應該注意。 + +#### 1. **狀態變更回呼必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回呼會告訴表格實例這將是一個受控狀態。如果您沒有指定對應的 `state` 值,該狀態將「凍結」其初始值。 + +```ts +class TableComponent { + sorting = signal([]) + + table = createAngularTable(() => ({ + columns: this.columns, + data: this.data(), + //... + state: { + sorting: this.sorting(), // 必需,因為我們使用了 `onSortingChange` + }, + onSortingChange: updater => { // 使 `state.sorting` 受控 + updater instanceof Function + ? this.sorting.update(updater) + : this.sorting.set(updater) + } + })) +} +``` + +#### 2. **更新器可以是原始值或回呼函數**。 + +`on[State]Change` 和 `onStateChange` 回呼的工作方式與 React 中的 `setState` 函數完全相同。更新器值可以是新的狀態值,也可以是接收先前的狀態值並返回新狀態值的回呼函數。 + +這有什麼影響?這意味著如果您想在任何 `on[State]Change` 回呼中加入一些額外的邏輯,您可以這樣做,但您需要檢查新的傳入更新器值是函數還是值。 + +這就是為什麼您會在上面的範例中看到 `updater instanceof Function ? this.state.update(updater) : this.state.set(updater)` 模式。此模式檢查更新器是否為函數,如果是,則使用先前的狀態值呼叫該函數以獲取新的狀態值,否則信號將需要呼叫 `signal.update` 而不是 `signal.set`。 + +### 狀態類型 + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,您可以導入和使用。這對於確保您為控制的狀態值使用正確的資料結構和屬性非常有用。 + +```ts +import {createAngularTable, type SortingState} from '@tanstack/angular-table' + +class TableComponent { + readonly sorting = signal([ + { + id: 'age', // 您應該會獲得 `id` 和 `desc` 屬性的自動完成 + desc: true, + } + ]) +} +``` diff --git a/docs/zh-hant/framework/lit/guide/table-state.md b/docs/zh-hant/framework/lit/guide/table-state.md new file mode 100644 index 0000000000..f6014bbc69 --- /dev/null +++ b/docs/zh-hant/framework/lit/guide/table-state.md @@ -0,0 +1,194 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:45:21.513Z' +title: 表格狀態 +--- +## Table State (Lit) 指南 + +TanStack Table 的核心是 **框架無關 (framework agnostic)** 的,這意味著無論你使用哪種框架,其 API 都保持一致。根據你所使用的框架,提供了適配器 (adapters) 來簡化與表格核心的互動。請參閱 Adapters 選單以查看可用的適配器。 + +### 存取表格狀態 + +你無需特別設定即可讓表格狀態運作。如果沒有傳遞任何值到 `state`、`initialState` 或任何 `on[State]Change` 表格選項中,表格將在內部自行管理其狀態。你可以使用 `table.getState()` 表格實例 API 來存取任何部分的內部狀態。 + +```ts +private tableController = new TableController(this); + +render() { + const table = this.tableController.table({ + columns, + data, + ... + }) + + console.log(table.getState()) //存取整個內部狀態 + console.log(table.getState().rowSelection) //僅存取行選取狀態 + // ... +} +``` + +### 自訂初始狀態 + +如果對於某些狀態,你只需要自訂其初始預設值,那麼你仍然不需要自行管理任何狀態。你可以簡單地在表格實例的 `initialState` 選項中設定值。 + +```ts +render() { + const table = this.tableController.table({ + columns, + data, + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降序排序 + } + ] + }, + }) + + return html`...`; +} +``` + +> **注意**:每個特定的狀態只能在 `initialState` 或 `state` 中指定,不能同時在兩者中設定。如果你將特定的狀態值同時傳遞到 `initialState` 和 `state`,`state` 中的初始化狀態將覆蓋 `initialState` 中的對應值。 + +### 受控狀態 (Controlled State) + +如果你需要在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 讓你能夠輕鬆地在自己的狀態管理系統中控制和管理任何或所有表格狀態。你可以通過將自己的狀態和狀態管理函數傳遞到 `state` 和 `on[State]Change` 表格選項中來實現這一點。 + +#### 個別受控狀態 + +你可以僅控制你需要輕鬆存取的狀態。如果不需要,你**不必**控制所有表格狀態。建議根據具體情況僅控制你需要的狀態。 + +為了控制特定的狀態,你需要同時將對應的 `state` 值和 `on[State]Change` 函數傳遞到表格實例中。 + +讓我們以「手動」伺服器端資料獲取場景中的篩選、排序和分頁為例。你可以將篩選、排序和分頁狀態儲存在自己的狀態管理中,但如果你的 API 不關心這些值,則可以忽略其他狀態,如欄位順序、欄位可見性等。 + +```jsx +import {html} from "lit"; + +@customElement('my-component') +class MyComponent extends LitElement { + @state() + private _sorting: SortingState = [] + + render() { + const table = this.tableController.table({ + columns, + data, + state: { + sorting: this._sorting, + }, + onSortingChange: updaterOrValue => { + if (typeof updaterOrValue === 'function') { + this._sorting = updaterOrValue(this._sorting) + } else { + this._sorting = updaterOrValue + } + }, + getSortedRowModel: getSortedRowModel(), + getCoreRowModel: getCoreRowModel(), + }) + + return html`...` + } +} +//... +``` + +#### 完全受控狀態 + +或者,你可以使用 `onStateChange` 表格選項來控制整個表格狀態。這會將整個表格狀態提升到你自己的狀態管理系統中。請謹慎使用此方法,因為你可能會發現將某些頻繁變化的狀態值(如 `columnSizingInfo` 狀態)提升到元件樹中可能會導致嚴重的效能問題。 + +可能需要一些額外的技巧來實現這一點。如果你使用 `onStateChange` 表格選項,`state` 的初始值必須填充所有相關的狀態值,以用於你想要使用的所有功能。你可以手動輸入所有初始狀態值,或者如下所示以特殊方式使用 `table.setOptions` API。 + +```ts + +private tableController = new TableController(this); + +@state() +private _tableState; + +render() { + const table = this.tableController.table({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel() + }) + const state = { ...table.initialState, ...this._tableState }; + table.setOptions(prev => ({ + ...prev, + state, + onStateChange: updater => { + this._tableState = + updater instanceof Function ? updater(state) : updater //任何狀態變更都會被推送到我們自己的狀態管理 + }, + })) + + return html`...`; +} +``` + +### 狀態變更回呼函數 (On State Change Callbacks) + +到目前為止,我們已經看到 `on[State]Change` 和 `onStateChange` 表格選項用於將表格狀態變更「提升」到我們自己的狀態管理中。然而,使用這些選項時有幾點需要注意。 + +#### 1. **狀態變更回呼函數必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回呼函數會告訴表格實例這將是一個受控狀態。如果你沒有指定對應的 `state` 值,該狀態將「凍結」在其初始值。 + +```jsx +@state() +private _sorting = []; +//... +render() { + const table = this.tableController.table({ + columns, + data, + state: { + sorting: this._sorting, + }, + onSortingChange: updaterOrValue => { + if (typeof updaterOrValue === 'function') { + this._sorting = updaterOrValue(this._sorting) + } else { + this._sorting = updaterOrValue + } + }, + getSortedRowModel: getSortedRowModel(), + getCoreRowModel: getCoreRowModel(), + }) + + return html`...`; +} +``` + +#### 2. **更新器可以是原始值或回呼函數**。 + +`on[State]Change` 和 `onStateChange` 回呼函數的工作方式與 React 中的 `setState` 函數完全相同。更新器值可以是新的狀態值,也可以是一個回呼函數,該函數接收先前的狀態值並返回新的狀態值。 + +這有什麼影響?這意味著如果你想在任何 `on[State]Change` 回呼函數中添加一些額外邏輯,你可以這樣做,但你需要檢查新的傳入更新器值是函數還是值。 + +這就是為什麼在上面的例子中你會看到 `updater instanceof Function ? updater(state.value) : updater` 模式。此模式檢查更新器是否為函數,如果是,則使用先前的狀態值呼叫該函數以獲取新的狀態值。 + +### 狀態類型 (State Types) + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,你可以導入並使用。這對於確保你為控制的狀態值使用正確的資料結構和屬性非常有用。 + +```tsx +import { TableController, type SortingState } from '@tanstack/lit-table' +//... +@state() +private _sorting: SortingState = [ + { + id: 'age', //你應該會看到 `id` 和 `desc` 屬性的自動完成 + desc: true, + } +] +``` diff --git a/docs/zh-hant/framework/lit/lit-table.md b/docs/zh-hant/framework/lit/lit-table.md new file mode 100644 index 0000000000..7bb845a8c6 --- /dev/null +++ b/docs/zh-hant/framework/lit/lit-table.md @@ -0,0 +1,64 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:42:27.947Z' +title: Lit 表格適配器 +--- +`@tanstack/lit-table` 適配器是核心表格邏輯的封裝層,其主要工作是以 "lit" 的方式管理狀態,並提供單元格/表頭/表尾模板的類型定義與渲染實現。 + +## 匯出項目 + +`@tanstack/lit-table` 重新匯出了 `@tanstack/table-core` 的所有 API 以及以下內容: + +### `TableController` + +這是一個響應式控制器 (reactive controller),提供一個 `table` API,該 API 接收 `options` 物件並回傳表格實例。 + +```ts +import { TableController } from '@tanstack/lit-table' + +@customElement('my-table-element') +class MyTableElement extends LitElement { + private tableController = new TableController(this) + + protected render() { + const table = this.tableController.table(options) + // ...渲染你的表格 + } +} +``` + +### `flexRender` + +一個用於渲染帶有動態值的單元格/表頭/表尾模板的實用函式。 + +範例: + +```jsx +import { flexRender } from '@tanstack/lit-table' +//... +return html` + + ${table + .getRowModel() + .rows.slice(0, 10) + .map( + row => html` + + ${row + .getVisibleCells() + .map( + cell => html` + + ${flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ` + )} + + ` + )} + +` +``` diff --git a/docs/zh-hant/framework/qwik/guide/table-state.md b/docs/zh-hant/framework/qwik/guide/table-state.md new file mode 100644 index 0000000000..41667b81d6 --- /dev/null +++ b/docs/zh-hant/framework/qwik/guide/table-state.md @@ -0,0 +1,179 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:45:17.145Z' +title: 表格狀態 +--- +## Table 狀態管理 (Qwik) 指南 + +TanStack Table 的核心是**框架無關 (framework agnostic)** 的,這意味著無論使用哪種框架,其 API 都保持一致。針對不同框架提供了適配器 (adapters) 來簡化與表格核心的互動。請參閱 Adapters 選單查看可用的適配器。 + +### 存取表格狀態 + +無需特別設定即可讓表格狀態正常運作。如果未向 `state`、`initialState` 或任何 `on[State]Change` 表格選項傳遞任何內容,表格將在內部自行管理狀態。您可以透過 `table.getState()` 表格實例 API 存取任何內部狀態。 + +```jsx +const table = useQwikTable({ + columns, + data, + //... +}) + +console.log(table.getState()) //存取整個內部狀態 +console.log(table.getState().rowSelection) //僅存取行選取狀態 +``` + +### 自訂初始狀態 + +若只需針對特定狀態自訂其初始預設值,仍無需自行管理任何狀態。只需在表格實例的 `initialState` 選項中設定值即可。 + +```jsx +const table = useQwikTable({ + columns, + data, + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降冪排序 + } + ] + }, + //... +}) +``` + +> **注意**:每個特定狀態只能在 `initialState` 或 `state` 其中一處指定,不可同時設定。若將特定狀態值同時傳遞給 `initialState` 和 `state`,則 `state` 中的初始化狀態將覆蓋 `initialState` 中的對應值。 + +### 受控狀態 (Controlled State) + +若需在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 可讓您輕鬆在自己的狀態管理系統中控制和管理部分或全部表格狀態。方法是將自己的狀態和狀態管理函式傳遞給 `state` 和 `on[State]Change` 表格選項。 + +#### 個別受控狀態 + +您可以僅控制需要輕鬆存取的狀態。若不需要,**不必**控制所有表格狀態。建議根據實際需求逐案控制所需狀態。 + +要控制特定狀態,需同時將對應的 `state` 值和 `on[State]Change` 函式傳遞給表格實例。 + +以「手動」伺服器端資料獲取情境中的篩選、排序和分頁為例。您可以將篩選、排序和分頁狀態儲存在自己的狀態管理中,但如果 API 不關心這些值,則可忽略其他狀態如欄位順序、欄位可見性等。 + +```jsx +const columnFilters = Qwik.useSignal([]) //無預設篩選條件 +const sorting = Qwik.useSignal([{ + id: 'age', + desc: true, //預設按年齡降冪排序 +}]) +const pagination = Qwik.useSignal({ pageIndex: 0, pageSize: 15 }) + +//使用受控狀態值獲取資料 +const tableQuery = useQuery({ + queryKey: ['users', columnFilters.value, sorting.value, pagination.value], + queryFn: () => fetchUsers(columnFilters.value, sorting.value, pagination.value), + //... +}) + +const table = useQwikTable({ + columns: columns.value, + data: tableQuery.data, + //... + state: { + columnFilters: columnFilters.value, //將受控狀態傳回表格(覆蓋內部狀態) + sorting: sorting.value, + pagination: pagination.value, + }, + onColumnFiltersChange: updater => { + columnFilters.value = updater instanceof Function ? updater(columnFilters.value) : updater //將 columnFilters 狀態提升至自己的狀態管理 + }, + onSortingChange: updater => { + sorting.value = updater instanceof Function ? updater(sorting.value) : updater + }, + onPaginationChange: updater => { + pagination.value = updater instanceof Function ? updater(pagination.value) : updater + }, +}) +//... +``` + +#### 完全受控狀態 + +或者,您可以使用 `onStateChange` 表格選項控制整個表格狀態。這會將整個表格狀態提升至您的狀態管理系統。請謹慎使用此方法,因為將某些頻繁變更的狀態值(如 `columnSizingInfo` 狀態)提升至元件樹可能會導致效能問題。 + +可能需要一些技巧來實現此功能。若使用 `onStateChange` 表格選項,則 `state` 的初始值必須填充所有相關狀態值,涵蓋您要使用的所有功能。您可以手動輸入所有初始狀態值,或如下所示特殊使用 `table.setOptions` API。 + +```jsx +//建立具有預設狀態值的表格實例 +const table = useQwikTable({ + columns, + data, + //... 注意:尚未傳入 `state` 值 +}) + + +const sate = Qwik.useSignal({ + ...table.initialState, //用表格實例的所有預設狀態值填充初始狀態 + pagination: { + pageIndex: 0, + pageSize: 15 //可選自訂初始分頁狀態 + } +}) + +//使用 table.setOptions API 將完全受控狀態合併到表格實例 +table.setOptions(prev => ({ + ...prev, //保留上方設定的其他選項 + state: state.value, //完全受控狀態覆蓋內部狀態 + onStateChange: updater => { + state.value = updater instanceof Function ? updater(state.value) : updater //任何狀態變更將推送至自己的狀態管理 + }, +})) +``` + +### 狀態變更回呼函式 + +目前,我們已看到 `on[State]Change` 和 `onStateChange` 表格選項如何將表格狀態變更「提升」至我們的狀態管理。但使用這些選項時需注意以下幾點。 + +#### 1. **狀態變更回呼函式必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回呼函式會告知表格實例此為受控狀態。若未指定對應的 `state` 值,該狀態將「凍結」為其初始值。 + +```jsx +const sorting = Qwik.useSignal([]) +//... +const table = useQwikTable({ + columns, + data, + //... + state: { + sorting: sorting.value, //必需,因為我們使用 `onSortingChange` + }, + onSortingChange: updater => { + sorting.value = updater instanceof Function ? updater(sorting) : updater //使 `state.sorting` 受控 + }, +}) +``` + +#### 2. **更新器 (Updaters) 可以是原始值或回呼函式**。 + +`on[State]Change` 和 `onStateChange` 回呼函式的工作方式與 React 中的 `setState` 函式完全相同。更新器值可以是新狀態值,也可以是接收先前狀態值並返回新狀態值的回呼函式。 + +這意味著什麼?這表示若想在 `on[State]Change` 回呼函式中加入額外邏輯,可以這樣做,但需檢查傳入的更新器值是函式還是值。 + +這就是為什麼在上面的範例中會看到 `updater instanceof Function ? updater(state.value) : updater` 模式。此模式檢查更新器是否為函式,若是,則呼叫該函式並傳入先前的狀態值以獲取新狀態值。 + +### 狀態類型 + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,可供匯入和使用。這有助於確保您為控制的狀態值使用正確的資料結構和屬性。 + +```tsx +import { useQwikTable, type SortingState } from '@tanstack/qwik-table' +//... +const sorting = Qwik.useSignal([ + { + id: 'age', //您應能獲得 `id` 和 `desc` 屬性的自動完成提示 + desc: true, + } +]) +``` diff --git a/docs/zh-hant/framework/qwik/qwik-table.md b/docs/zh-hant/framework/qwik/qwik-table.md new file mode 100644 index 0000000000..3a9cea9861 --- /dev/null +++ b/docs/zh-hant/framework/qwik/qwik-table.md @@ -0,0 +1,48 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:42:22.017Z' +title: Qwik 表格適配器 +--- +`@tanstack/qwik-table` 適配器是核心表格邏輯的封裝層,其主要工作是依照 Qwik 的方式管理狀態,並提供單元格/表頭/表尾模板的型別與渲染實作。 + +## 導出項目 + +`@tanstack/qwik-table` 重新導出了 `@tanstack/table-core` 的所有 API 以及以下內容: + +### `useQwikTable` + +接收一個 `options` 物件,並從帶有 `NoSerialize` 的 Qwik Store 返回一個表格實例。 + +```ts +import { useQwikTable } from '@tanstack/qwik-table' + +const table = useQwikTable(options) +// ...渲染你的表格 + +``` + +### `flexRender` + +一個用於渲染帶有動態值的單元格/表頭/表尾模板的實用函數。 + +範例: + +```jsx +import { flexRender } from '@tanstack/qwik-table' +//... +return ( + + {table.getRowModel().rows.map(row => { + return ( + + {row.getVisibleCells().map(cell => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ) + })} + +); +``` diff --git a/docs/zh-hant/framework/react/guide/table-state.md b/docs/zh-hant/framework/react/guide/table-state.md new file mode 100644 index 0000000000..5e2a53b2d3 --- /dev/null +++ b/docs/zh-hant/framework/react/guide/table-state.md @@ -0,0 +1,205 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:45:19.587Z' +title: 表格狀態 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [綜合範例](../examples/kitchen-sink) +- [完全控制](../examples/fully-controlled) + +## 表格狀態 (React) 指南 + +TanStack Table 的核心是 **框架無關 (framework agnostic)** 的,這意味著無論你使用哪種框架,其 API 都是相同的。根據你所使用的框架,提供了適配器 (Adapters) 來簡化與表格核心的互動。請參閱「適配器」選單以查看可用的適配器。 + +### 存取表格狀態 + +你無需特別設定即可讓表格狀態正常運作。如果你沒有傳遞任何值給 `state`、`initialState` 或任何 `on[State]Change` 表格選項,表格將在內部自行管理其狀態。你可以透過 `table.getState()` 表格實例 API 存取任何部分的內部狀態。 + +```jsx +const table = useReactTable({ + columns, + data, + //... +}) + +console.log(table.getState()) //存取整個內部狀態 +console.log(table.getState().rowSelection) //僅存取行選取狀態 +``` + +### 自訂初始狀態 + +如果你只需要為某些狀態自訂其初始預設值,仍然不需要自行管理任何狀態。你可以簡單地在表格實例的 `initialState` 選項中設定值。 + +```jsx +const table = useReactTable({ + columns, + data, + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降序排序 + } + ] + }, + //... +}) +``` + +> **注意**:每個特定狀態只能在 `initialState` 或 `state` 中指定,不可同時存在。如果你將特定狀態值同時傳遞給 `initialState` 和 `state`,`state` 中的初始化狀態將覆蓋 `initialState` 中的對應值。 + +### 受控狀態 + +如果你需要在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 讓你可以輕鬆地在自己的狀態管理系統中控制和管理任何或所有表格狀態。你可以透過將自己的狀態和狀態管理函式傳遞給 `state` 和 `on[State]Change` 表格選項來實現這一點。 + +#### 個別受控狀態 + +你可以僅控制你需要輕鬆存取的狀態。如果不需要,你不必控制所有表格狀態。建議根據實際情況僅控制你需要的狀態。 + +為了控制特定狀態,你需要同時將對應的 `state` 值和 `on[State]Change` 函式傳遞給表格實例。 + +讓我們以「手動」伺服器端資料擷取情境中的篩選、排序和分頁為例。你可以將篩選、排序和分頁狀態儲存在自己的狀態管理中,但如果你的 API 不關心這些值,則可以忽略其他狀態,如欄位順序、欄位可見性等。 + +```jsx +const [columnFilters, setColumnFilters] = React.useState([]) //無預設篩選條件 +const [sorting, setSorting] = React.useState([{ + id: 'age', + desc: true, //預設按年齡降序排序 +}]) +const [pagination, setPagination] = React.useState({ pageIndex: 0, pageSize: 15 }) + +//使用我們受控的狀態值來擷取資料 +const tableQuery = useQuery({ + queryKey: ['users', columnFilters, sorting, pagination], + queryFn: () => fetchUsers(columnFilters, sorting, pagination), + //... +}) + +const table = useReactTable({ + columns, + data: tableQuery.data, + //... + state: { + columnFilters, //將受控狀態傳回表格(覆蓋內部狀態) + sorting, + pagination + }, + onColumnFiltersChange: setColumnFilters, //將 columnFilters 狀態提升到我們自己的狀態管理 + onSortingChange: setSorting, + onPaginationChange: setPagination, +}) +//... +``` + +#### 完全受控狀態 + +或者,你可以使用 `onStateChange` 表格選項來控制整個表格狀態。這會將整個表格狀態提升到你自己的狀態管理系統中。請謹慎使用此方法,因為你可能會發現將某些頻繁變更的狀態值(如 `columnSizingInfo` 狀態)提升到 React 樹中可能會導致嚴重的效能問題。 + +可能需要一些額外的技巧來實現這一點。如果你使用 `onStateChange` 表格選項,`state` 的初始值必須填充所有相關的狀態值,以用於你想要使用的所有功能。你可以手動輸入所有初始狀態值,或者以如下所示的方式使用 `table.setOptions` API。 + +```jsx +//建立一個帶有預設狀態值的表格實例 +const table = useReactTable({ + columns, + data, + //... 注意:尚未傳入 `state` 值 +}) + + +const [state, setState] = React.useState({ + ...table.initialState, //使用表格實例中的所有預設狀態值填充初始狀態 + pagination: { + pageIndex: 0, + pageSize: 15 //可選自訂初始分頁狀態 + } +}) + +//使用 table.setOptions API 將我們完全受控的狀態合併到表格實例中 +table.setOptions(prev => ({ + ...prev, //保留我們上面設定的任何其他選項 + state, //我們完全受控的狀態覆蓋內部狀態 + onStateChange: setState //任何狀態變更都會被推送到我們自己的狀態管理 +})) +``` + +### 狀態變更回呼函式 + +到目前為止,我們已經看到 `on[State]Change` 和 `onStateChange` 表格選項可以將表格狀態變更「提升」到我們自己的狀態管理中。然而,關於使用這些選項,有幾點你應該注意。 + +#### 1. **狀態變更回呼函式必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回呼函式會告訴表格實例這將是一個受控狀態。如果你沒有指定對應的 `state` 值,該狀態將「凍結」在其初始值。 + +```jsx +const [sorting, setSorting] = React.useState([]) +//... +const table = useReactTable({ + columns, + data, + //... + state: { + sorting, //必需,因為我們正在使用 `onSortingChange` + }, + onSortingChange: setSorting, //使 `state.sorting` 受控 +}) +``` + +#### 2. **更新器可以是原始值或回呼函式**。 + +`on[State]Change` 和 `onStateChange` 回呼函式的工作方式與 React 中的 `setState` 函式完全相同。更新器值可以是一個新的狀態值,也可以是一個接收先前狀態值並返回新狀態值的回呼函式。 + +這有什麼影響?這意味著如果你想在任何 `on[State]Change` 回呼函式中加入一些額外邏輯,你可以這樣做,但你需要檢查新的傳入更新器值是函式還是值。 + +```jsx +const [sorting, setSorting] = React.useState([]) +const [pagination, setPagination] = React.useState({ pageIndex: 0, pageSize: 10 }) + +const table = useReactTable({ + columns, + data, + //... + state: { + pagination, + sorting, + } + //語法 1 + onPaginationChange: (updater) => { + setPagination(old => { + const newPaginationValue = updater instanceof Function ? updater(old) : updater + //對新的分頁值進行一些操作 + //... + return newPaginationValue + }) + }, + //語法 2 + onSortingChange: (updater) => { + const newSortingValue = updater instanceof Function ? updater(sorting) : updater + //對新的排序值進行一些操作 + //... + setSorting(updater) //正常的狀態更新 + } +}) +``` + +### 狀態類型 + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,你可以導入和使用。這對於確保你為控制的狀態值使用正確的資料結構和屬性非常有用。 + +```tsx +import { useReactTable, type SortingState } from '@tanstack/react-table' +//... +const [sorting, setSorting] = React.useState([ + { + id: 'age', //你應該會看到 `id` 和 `desc` 屬性的自動完成 + desc: true, + } +]) +``` diff --git a/docs/zh-hant/framework/react/react-table.md b/docs/zh-hant/framework/react/react-table.md new file mode 100644 index 0000000000..9265c6a1ab --- /dev/null +++ b/docs/zh-hant/framework/react/react-table.md @@ -0,0 +1,20 @@ +--- +source-updated-at: '2024-01-24T21:39:34.000Z' +translation-updated-at: '2025-05-08T23:42:10.780Z' +title: React 表格適配器 +--- +`@tanstack/react-table` 轉接器 (adapter) 是核心表格邏輯的封裝層,其主要職責是以「React」方式管理狀態,並提供單元格/表頭/表尾模板的類型定義與渲染實作。 + +## `useReactTable` + +接收一個 `options` 物件並回傳表格實例。 + +```tsx +import { useReactTable } from '@tanstack/react-table' + +function App() { + const table = useReactTable(options) + + // ...render your table +} +``` diff --git a/docs/zh-hant/framework/solid/guide/table-state.md b/docs/zh-hant/framework/solid/guide/table-state.md new file mode 100644 index 0000000000..8233f0f036 --- /dev/null +++ b/docs/zh-hant/framework/solid/guide/table-state.md @@ -0,0 +1,222 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:45:19.640Z' +title: 表格狀態 +--- +## Table State (Solid) 指南 + +TanStack Table 的核心是 **框架無關 (framework agnostic)** 的,這意味著無論您使用哪種框架,其 API 都是相同的。根據您使用的框架,提供了適配器 (Adapters) 來簡化與表格核心的互動。請參閱適配器選單以查看可用的適配器。 + +### 存取表格狀態 + +您無需特別設定即可讓表格狀態運作。如果您沒有向 `state`、`initialState` 或任何 `on[State]Change` 表格選項傳遞任何內容,表格將在內部管理自己的狀態。您可以使用 `table.getState()` 表格實例 API 來存取此內部狀態的任何部分。 + +```jsx +const table = createSolidTable({ + columns, + get data() { + return data() + }, + //... +}) + +console.log(table.getState()) //存取整個內部狀態 +console.log(table.getState().rowSelection) //僅存取行選擇狀態 +``` + +### 自訂初始狀態 + +如果您只需要為某些狀態自訂其初始預設值,您仍然不需要自行管理任何狀態。您只需在表格實例的 `initialState` 選項中設定值即可。 + +```jsx +const table = createSolidTable({ + columns, + data, + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降序排序 + } + ] + }, + //... +}) +``` + +> **注意**:每個特定狀態只能在 `initialState` 或 `state` 中指定,但不能同時指定。如果您將特定狀態值傳遞給 `initialState` 和 `state`,則 `state` 中的初始化狀態將覆蓋 `initialState` 中的任何對應值。 + +### 受控狀態 + +如果您需要在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 讓您可以輕鬆地在自己的狀態管理系統中控制和管理任何或所有表格狀態。您可以通過將自己的狀態和狀態管理函數傳遞給 `state` 和 `on[State]Change` 表格選項來實現這一點。 + +#### 個別受控狀態 + +您可以僅控制您需要輕鬆存取的狀態。如果不需要,您不必控制所有表格狀態。建議根據具體情況僅控制您需要的狀態。 + +為了控制特定狀態,您需要將對應的 `state` 值和 `on[State]Change` 函數傳遞給表格實例。 + +讓我們以「手動」伺服器端數據獲取場景中的篩選、排序和分頁為例。您可以將篩選、排序和分頁狀態存儲在自己的狀態管理中,但如果您的 API 不關心這些值,則可以忽略其他狀態,如欄位順序、欄位可見性等。 + +```jsx +const [columnFilters, setColumnFilters] = createSignal([]) //無預設篩選 +const [sorting, setSorting] = createSignal([{ + id: 'age', + desc: true, //預設按年齡降序排序 +}]) +const [pagination, setPagination] = createSignal({ pageIndex: 0, pageSize: 15 }) + +//使用我們的受控狀態值來獲取數據 +const tableQuery = createQuery({ + queryKey: ['users', columnFilters, sorting, pagination], + queryFn: () => fetchUsers(columnFilters, sorting, pagination), + //... +}) + +const table = createSolidTable({ + columns, + get data() { + return tableQuery.data() + }, + //... + state: { + get columnFilters() { + return columnFilters() //將受控狀態傳回表格(覆蓋內部狀態) + }, + get sorting() { + return sorting() + }, + get pagination() { + return pagination() + }, + }, + onColumnFiltersChange: setColumnFilters, //將 columnFilters 狀態提升到我們自己的狀態管理 + onSortingChange: setSorting, + onPaginationChange: setPagination, +}) +//... +``` + +#### 完全受控狀態 + +或者,您可以使用 `onStateChange` 表格選項來控制整個表格狀態。這將把整個表格狀態提升到您自己的狀態管理系統中。請謹慎使用此方法,因為您可能會發現將一些頻繁變化的狀態值(如 `columnSizingInfo` 狀態)提升到 Solid 樹中可能會導致性能問題。 + +可能需要一些技巧來實現這一點。如果您使用 `onStateChange` 表格選項,則 `state` 的初始值必須填充您想要使用的所有相關狀態值。您可以手動輸入所有初始狀態值,或者使用 `table.setOptions` API 的特殊方式,如下所示。 + +```jsx +//創建一個帶有預設狀態值的表格實例 +const table = createSolidTable({ + columns, + get data() { + return data() + }, + //... 注意:尚未傳入 `state` 值 +}) + + +const [state, setState] = createSignal({ + ...table.initialState, //用表格實例的所有預設狀態值填充初始狀態 + pagination: { + pageIndex: 0, + pageSize: 15 //可選自訂初始分頁狀態 + } +}) + +//使用 table.setOptions API 將我們的完全受控狀態合併到表格實例上 +table.setOptions(prev => ({ + ...prev, //保留我們在上面設定的任何其他選項 + get state() { + return state() //我們的完全受控狀態覆蓋內部狀態 + }, + onStateChange: setState //任何狀態更改都將推送到我們自己的狀態管理 +})) +``` + +### 狀態更改回調 + +到目前為止,我們已經看到 `on[State]Change` 和 `onStateChange` 表格選項可以將表格狀態更改「提升」到我們自己的狀態管理中。然而,關於使用這些選項,有幾點您應該注意。 + +#### 1. **狀態更改回調必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回調告訴表格實例這將是一個受控狀態。如果您沒有指定對應的 `state` 值,該狀態將「凍結」其初始值。 + +```jsx +const [sorting, setSorting] = createSignal([]) +//... +const table = createSolidTable({ + columns, + data, + //... + state: { + get sorting() { + return sorting() //必需,因為我們正在使用 `onSortingChange` + }, + }, + onSortingChange: setSorting, //使 `state.sorting` 受控 +}) +``` + +#### 2. **更新器可以是原始值或回調函數**。 + +`on[State]Change` 和 `onStateChange` 回調的工作方式與 React (Solid Setters) 中的 `setState` 函數完全相同。更新器值可以是新的狀態值,也可以是接收先前狀態值並返回新狀態值的回調函數。 + +這有什麼影響?這意味著如果您想在任何 `on[State]Change` 回調中添加一些額外邏輯,您可以這樣做,但您需要檢查新的傳入更新器值是函數還是值。 + +```jsx +const [sorting, setSorting] = createSignal([]) +const [pagination, setPagination] = createSignal({ pageIndex: 0, pageSize: 10 }) + +const table = createSolidTable({ + get columns() { + return columns() + }, + get data() { + return data() + }, + //... + state: { + get pagination() { + return pagination() + }, + get sorting() { + return sorting() + }, + } + //語法 1 + onPaginationChange: (updater) => { + setPagination(old => { + const newPaginationValue = updater instanceof Function ? updater(old) : updater + //對新的分頁值進行操作 + //... + return newPaginationValue + }) + }, + //語法 2 + onSortingChange: (updater) => { + const newSortingValue = updater instanceof Function ? updater(sorting) : updater + //對新的排序值進行操作 + //... + setSorting(updater) //正常狀態更新 + } +}) +``` + +### 狀態類型 + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,您可以導入和使用。這對於確保您為控制的狀態值使用正確的數據結構和屬性非常有用。 + +```tsx +import { createSolidTable, type SortingState } from '@tanstack/solid-table' +//... +const [sorting, setSorting] = createSignal([ + { + id: 'age', //您應該可以獲得 `id` 和 `desc` 屬性的自動完成 + desc: true, + } +]) +``` diff --git a/docs/zh-hant/framework/solid/solid-table.md b/docs/zh-hant/framework/solid/solid-table.md new file mode 100644 index 0000000000..56ce6ab3fd --- /dev/null +++ b/docs/zh-hant/framework/solid/solid-table.md @@ -0,0 +1,20 @@ +--- +source-updated-at: '2024-01-24T21:39:34.000Z' +translation-updated-at: '2025-05-08T23:42:05.918Z' +title: Solid 表格適配器 +--- +`@tanstack/solid-table` 轉接器 (adapter) 是核心表格邏輯的封裝層,其主要工作是遵循 Solid 的方式管理狀態 (state),並提供單元格 (cell)/表頭 (header)/表尾 (footer) 模板的型別 (types) 與渲染實作 (rendering implementation)。 + +## `createSolidTable` + +接收一個 `options` 物件並回傳表格實例。 + +```tsx +import { createSolidTable } from '@tanstack/solid-table' + +function App() { + const table = createSolidTable(options) + + // ...render your table +} +``` diff --git a/docs/zh-hant/framework/svelte/guide/table-state.md b/docs/zh-hant/framework/svelte/guide/table-state.md new file mode 100644 index 0000000000..98928c683b --- /dev/null +++ b/docs/zh-hant/framework/svelte/guide/table-state.md @@ -0,0 +1,261 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:45:24.623Z' +title: 表格狀態 +--- +## Table State (Svelte) 指南 + +TanStack Table 的核心是 **框架無關 (framework agnostic)** 的,這意味著無論您使用哪種框架,其 API 都保持相同。根據您使用的框架,提供了適配器 (Adapters) 來簡化與表格核心的互動。請參閱 Adapters 選單以查看可用的適配器。 + +### 存取表格狀態 + +您無需特別設定即可讓表格狀態運作。如果未向 `state`、`initialState` 或任何 `on[State]Change` 表格選項傳遞任何內容,表格將在內部管理自己的狀態。您可以使用 `table.getState()` 表格實例 API 存取此內部狀態的任何部分。 + +```jsx +const options = writable({ + columns, + data, + //... +}) + +const table = createSvelteTable(options) + +console.log(table.getState()) //存取整個內部狀態 +console.log(table.getState().rowSelection) //僅存取行選取狀態 +``` + +### 自訂初始狀態 + +如果您只需要為某些狀態自訂其初始預設值,仍然無需自行管理任何狀態。您只需在表格實例的 `initialState` 選項中設定值即可。 + +```jsx +const options = writable({ + columns, + data, + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降序排序 + } + ] + }, + //... +}) + +const table = createSvelteTable(options) +``` + +> **注意**:每個特定狀態只能在 `initialState` 或 `state` 其中之一指定,不可同時設定。如果將特定狀態值同時傳遞給 `initialState` 和 `state`,則 `state` 中的初始化狀態將覆蓋 `initialState` 中的對應值。 + +### 受控狀態 (Controlled State) + +如果您需要在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 讓您可以輕鬆地在自己的狀態管理系統中控制和管理的任何或所有表格狀態。您可以通過將自己的狀態和狀態管理函式傳遞給 `state` 和 `on[State]Change` 表格選項來實現這一點。 + +#### 個別受控狀態 + +您可以僅控制您需要輕鬆存取的狀態。如果不需要,您不必控制所有表格狀態。建議根據具體情況僅控制您需要的狀態。 + +為了控制特定狀態,您需要將對應的 `state` 值和 `on[State]Change` 函式傳遞給表格實例。 + +讓我們以「手動」伺服器端資料獲取情境中的過濾、排序和分頁為例。您可以將過濾、排序和分頁狀態儲存在自己的狀態管理中,但如果您的 API 不關心這些值,則可以忽略其他狀態,如欄位順序、欄位可見性等。 + +```ts +let sorting = [ + { + id: 'age', + desc: true, //預設按年齡降序排序 + }, +] +const setSorting = updater => { + if (updater instanceof Function) { + sorting = updater(sorting) + } else { + sorting = updater + } + options.update(old => ({ + ...old, + state: { + ...old.state, + sorting, + }, + })) +} + +let columnFilters = [] //無預設過濾器 +const setColumnFilters = updater => { + if (updater instanceof Function) { + columnFilters = updater(columnFilters) + } else { + columnFilters = updater + } + options.update(old => ({ + ...old, + state: { + ...old.state, + columnFilters, + }, + })) +} + +let pagination = { pageIndex: 0, pageSize: 15 } //預設分頁 +const setPagination = updater => { + if (updater instanceof Function) { + pagination = updater(pagination) + } else { + pagination = updater + } + options.update(old => ({ + ...old, + state: { + ...old.state, + pagination, + }, + })) +} + +//使用我們的受控狀態值來獲取資料 +const tableQuery = createQuery({ + queryKey: ['users', columnFilters, sorting, pagination], + queryFn: () => fetchUsers(columnFilters, sorting, pagination), + //... +}) + +const options = writable({ + columns, + data: tableQuery.data, + //... + state: { + columnFilters, //將受控狀態傳回表格 (覆蓋內部狀態) + sorting, + pagination + }, + onColumnFiltersChange: setColumnFilters, //將 columnFilters 狀態提升到我們自己的狀態管理 + onSortingChange: setSorting, + onPaginationChange: setPagination, +}) + +const table = createSvelteTable(options) +//... +``` + +#### 完全受控狀態 + +或者,您可以使用 `onStateChange` 表格選項控制整個表格狀態。這會將整個表格狀態提升到您自己的狀態管理系統中。請謹慎使用此方法,因為您可能會發現將某些頻繁變化的狀態值(如 `columnSizingInfo` 狀態)提升到 Svelte 樹中可能會導致效能問題。 + +可能需要一些技巧才能使其運作。如果您使用 `onStateChange` 表格選項,則 `state` 的初始值必須填充所有相關狀態值,以用於您想要使用的所有功能。您可以手動輸入所有初始狀態值,或使用 `table.setOptions` API,如下所示。 + +```jsx +//建立一個帶有預設狀態值的表格實例 +const options = writable({ + columns, + data, + //... 注意:尚未傳入 `state` 值 +}) +const table = createSvelteTable(options) + +let state = { + ...table.initialState, //用表格實例中的所有預設狀態值填充初始狀態 + pagination: { + pageIndex: 0, + pageSize: 15 //可選自訂初始分頁狀態 + } +} +const setState = updater => { + if (updater instanceof Function) { + state = updater(state) + } else { + state = updater + } + options.update(old => ({ + ...old, + state, + })) +} + +//使用 table.setOptions API 將我們的完全受控狀態合併到表格實例上 +table.setOptions(prev => ({ + ...prev, //保留我們上面設定的任何其他選項 + state, //我們的完全受控狀態覆蓋內部狀態 + onStateChange: setState //任何狀態變更將被提升到我們自己的狀態管理 +})) +``` + +### 狀態變更回呼 (On State Change Callbacks) + +到目前為止,我們已經看到 `on[State]Change` 和 `onStateChange` 表格選項如何將表格狀態變更「提升」到我們自己的狀態管理中。然而,使用這些選項時有一些需要注意的事項。 + +#### 1. **狀態變更回呼必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回呼會告訴表格實例這將是一個受控狀態。如果您未指定對應的 `state` 值,該狀態將「凍結」為其初始值。 + +```ts +let sorting = [] +const setSorting = updater => { + if (updater instanceof Function) { + sorting = updater(sorting) + } else { + sorting = updater + } + options.update(old => ({ + ...old, + state: { + ...old.state, + sorting, + }, + })) +} +//... +const options = writable({ + columns, + data, + //... + state: { + sorting, //必需,因為我們使用了 `onSortingChange` + }, + onSortingChange: setSorting, //使 `state.sorting` 受控 +}) +const table = createSvelteTable(options) +``` + +#### 2. **更新器可以是原始值或回呼函式**。 + +`on[State]Change` 和 `onStateChange` 回呼的工作方式與 React 中的 `setState` 函式完全相同。更新器值可以是新的狀態值,也可以是接收先前狀態值並返回新狀態值的回呼函式。 + +這意味著什麼?這意味著如果您想在 `on[State]Change` 回呼中添加一些額外邏輯,可以這樣做,但需要檢查新的傳入更新器值是函式還是值。 + +這就是為什麼您在上面的 `setState` 函式中看到 `if (updater instanceof Function)` 檢查的原因。 + +### 狀態類型 (State Types) + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,您可以導入和使用。這對於確保您為控制的狀態值使用正確的資料結構和屬性非常有用。 + +```ts +import { createSvelteTable, type SortingState, type Updater } from '@tanstack/svelte-table' +//... +let sorting: SortingState[] = [ + { + id: 'age', //您應該會看到 `id` 和 `desc` 屬性的自動完成 + desc: true, + } +] +const setSorting = (updater: Updater) => { + if (updater instanceof Function) { + sorting = updater(sorting) + } else { + sorting = updater + } + options.update(old => ({ + ...old, + state: { + ...old.state, + sorting, + }, + })) +} +``` diff --git a/docs/zh-hant/framework/svelte/svelte-table.md b/docs/zh-hant/framework/svelte/svelte-table.md new file mode 100644 index 0000000000..a368ea2041 --- /dev/null +++ b/docs/zh-hant/framework/svelte/svelte-table.md @@ -0,0 +1,20 @@ +--- +source-updated-at: '2024-01-24T21:39:34.000Z' +translation-updated-at: '2025-05-08T23:42:03.110Z' +title: Svelte 表格適配器 +--- +`@tanstack/svelte-table` 轉接器 (adapter) 是核心表格邏輯的封裝層,其主要工作是以「Svelte」的方式管理狀態,並提供類型 (types) 以及單元格 (cell)/表頭 (header)/表尾 (footer) 模板的渲染實作 (implementation)。 + +## `createSvelteTable` + +接收一個 `options` 物件並回傳表格實例。 + +```svelte + +``` diff --git a/docs/zh-hant/framework/vanilla/guide/table-state.md b/docs/zh-hant/framework/vanilla/guide/table-state.md new file mode 100644 index 0000000000..7b46ac48de --- /dev/null +++ b/docs/zh-hant/framework/vanilla/guide/table-state.md @@ -0,0 +1,6 @@ +--- +source-updated-at: '2024-03-22T06:50:43.000Z' +translation-updated-at: '2025-05-08T23:44:06.209Z' +title: 表格狀態 +--- +## 表格狀態 (Vanilla JS) 指南 diff --git a/docs/zh-hant/framework/vanilla/table-core.md b/docs/zh-hant/framework/vanilla/table-core.md new file mode 100644 index 0000000000..4675b3e56e --- /dev/null +++ b/docs/zh-hant/framework/vanilla/table-core.md @@ -0,0 +1,5 @@ +--- +source-updated-at: '2024-03-22T06:50:43.000Z' +translation-updated-at: '2025-05-08T23:41:54.602Z' +--- + diff --git a/docs/zh-hant/framework/vue/guide/table-state.md b/docs/zh-hant/framework/vue/guide/table-state.md new file mode 100644 index 0000000000..8bd438e82a --- /dev/null +++ b/docs/zh-hant/framework/vue/guide/table-state.md @@ -0,0 +1,249 @@ +--- +source-updated-at: '2024-08-10T14:15:46.000Z' +translation-updated-at: '2025-05-08T23:45:17.806Z' +title: 表格狀態 +--- +## 表格狀態 (Vue) 指南 + +TanStack Table 的核心是**框架無關 (framework agnostic)** 的,這意味著無論您使用哪種框架,其 API 都是相同的。根據您使用的框架,提供了適配器 (adapters) 來簡化與表格核心的互動。請參閱適配器選單以查看可用的適配器。 + +### 存取表格狀態 + +您無需特別設定即可讓表格狀態運作。如果您沒有向 `state`、`initialState` 或任何 `on[State]Change` 表格選項傳入任何內容,表格將在內部管理自己的狀態。您可以使用 `table.getState()` 表格實例 API 來存取此內部狀態的任何部分。 + +```ts +const table = useVueTable({ + columns, + data: dataRef, // 支援響應式資料 + //... +}) + +console.log(table.getState()) //存取整個內部狀態 +console.log(table.getState().rowSelection) //僅存取行選擇狀態 +``` + +### 使用響應式資料 + +> **v8.20.0 新增功能** + +`useVueTable` 鉤子現在支援響應式資料。這意味著您可以將包含資料的 Vue `ref` 或 `computed` 傳遞給 `data` 選項。表格將自動響應資料的變更。 + +```ts +const columns = [ + { accessor: 'id', Header: 'ID' }, + { accessor: 'name', Header: 'Name' } +] + +const dataRef = ref([ + { id: 1, name: 'John' }, + { id: 2, name: 'Jane' } +]) + +const table = useVueTable({ + columns, + data: dataRef, // 傳遞響應式資料 ref +}) + +// 之後,更新 dataRef 將自動更新表格 +dataRef.value = [ + { id: 1, name: 'John' }, + { id: 2, name: 'Jane' }, + { id: 3, name: 'Doe' } +] +``` + +> ⚠️ 出於效能考慮,底層使用了 `shallowRef`,這意味著資料不是深度響應的,只有 `.value` 是。要更新資料,您必須直接變更資料。 + +```ts +const dataRef = ref([ + { id: 1, name: 'John' }, + { id: 2, name: 'Jane' } +]) + +// 這將不會更新表格 ❌ +dataRef.value.push({ id: 4, name: 'John' }) + +// 這將更新表格 ✅ +dataRef.value = [ + ...dataRef.value, + { id: 4, name: 'John' } +] +``` + +### 自訂初始狀態 + +如果您只需要為某些狀態自訂其初始預設值,您仍然不需要自行管理任何狀態。您只需在表格實例的 `initialState` 選項中設定值即可。 + +```jsx +const table = useVueTable({ + columns, + data, + initialState: { + columnOrder: ['age', 'firstName', 'lastName'], //自訂初始欄位順序 + columnVisibility: { + id: false //預設隱藏 id 欄位 + }, + expanded: true, //預設展開所有行 + sorting: [ + { + id: 'age', + desc: true //預設按年齡降序排序 + } + ] + }, + //... +}) +``` + +> **注意**:每個特定狀態只能在 `initialState` 或 `state` 中指定,但不能同時指定。如果您將特定狀態值同時傳遞給 `initialState` 和 `state`,則 `state` 中的初始化狀態將覆蓋 `initialState` 中的任何對應值。 + +### 受控狀態 + +如果您需要在應用程式的其他區域輕鬆存取表格狀態,TanStack Table 讓您可以輕鬆地在自己的狀態管理系統中控制和管理的任何或所有表格狀態。您可以通過將自己的狀態和狀態管理函數傳遞給 `state` 和 `on[State]Change` 表格選項來實現這一點。 + +#### 個別受控狀態 + +您可以僅控制您需要輕鬆存取的狀態。如果不需要,您不必控制所有表格狀態。建議根據具體情況僅控制您需要的狀態。 + +為了控制特定狀態,您需要將對應的 `state` 值和 `on[State]Change` 函數都傳遞給表格實例。 + +讓我們以「手動」伺服器端資料獲取場景中的篩選、排序和分頁為例。您可以將篩選、排序和分頁狀態存儲在自己的狀態管理中,但如果您的 API 不關心這些值,則可以忽略其他狀態,如欄位順序、欄位可見性等。 + +```ts +const columnFilters = ref([]) //無預設篩選條件 +const sorting = ref([{ + id: 'age', + desc: true, //預設按年齡降序排序 +}]) +const pagination = ref({ pageIndex: 0, pageSize: 15 } + +//使用我們受控的狀態值來獲取資料 +const tableQuery = useQuery({ + queryKey: ['users', columnFilters, sorting, pagination], + queryFn: () => fetchUsers(columnFilters, sorting, pagination), + //... +}) + +const table = useVueTable({ + columns, + data: tableQuery.data, + //... + state: { + get columnFilters() { + return columnFilters.value + }, + get sorting() { + return sorting.value + }, + get pagination() { + return pagination.value + } + }, + onColumnFiltersChange: updater => { + columnFilters.value = + updater instanceof Function + ? updater(columnFilters.value) + : updater + }, + onSortingChange: updater => { + sorting.value = + updater instanceof Function + ? updater(sorting.value) + : updater + }, + onPaginationChange: updater => { + pagination.value = + updater instanceof Function + ? updater(pagination.value) + : updater + }, +}) +//... +``` + +#### 完全受控狀態 + +或者,您可以使用 `onStateChange` 表格選項來控制整個表格狀態。這將把整個表格狀態提升到您自己的狀態管理系統中。請謹慎使用此方法,因為您可能會發現將一些頻繁變更的狀態值(如 `columnSizingInfo` 狀態)提升到 React 樹中可能會導致效能問題。 + +可能需要一些技巧來實現這一點。如果您使用 `onStateChange` 表格選項,則 `state` 的初始值必須填充您想要使用的所有相關狀態值。您可以手動輸入所有初始狀態值,或者使用 `table.setOptions` API,如下所示。 + +```jsx +//使用預設狀態值建立表格實例 +const table = useVueTable({ + get columns() { + return columns.value + }, + data, + //... 注意:尚未傳入 `state` 值 +}) + +const state = ref({ + ...table.initialState, + pagination: { + pageIndex: 0, + pageSize: 15 + } +}) +const setState = updater => { + state.value = updater instanceof Function ? updater(state.value) : updater +} + +//使用 table.setOptions API 將我們完全受控的狀態合併到表格實例中 +table.setOptions(prev => ({ + ...prev, //保留我們上面設定的任何其他選項 + get state() { + return state.value + }, + onStateChange: setState //任何狀態變更將被提升到我們自己的狀態管理 +})) +``` + +### 狀態變更回呼 + +到目前為止,我們已經看到 `on[State]Change` 和 `onStateChange` 表格選項如何將表格狀態變更「提升」到我們自己的狀態管理中。然而,使用這些選項時有一些需要注意的事項。 + +#### 1. **狀態變更回呼必須在 `state` 選項中有對應的狀態值**。 + +指定 `on[State]Change` 回呼會告訴表格實例這將是一個受控狀態。如果您沒有指定對應的 `state` 值,該狀態將「凍結」其初始值。 + +```jsx +const sorting = ref([]) +const setSorting = updater => { + sorting.value = updater instanceof Function ? updater(sorting.value) : updater +} +//... +const table = useVueTable({ + columns, + data, + //... + state: { + get sorting() { + return sorting //必需,因為我們正在使用 `onSortingChange` + }, + }, + onSortingChange: setSorting, //使 `state.sorting` 受控 +}) +``` + +#### 2. **更新器可以是原始值或回呼函數**。 + +`on[State]Change` 和 `onStateChange` 回呼的工作方式與 React 中的 `setState` 函數完全相同。更新器值可以是新的狀態值,也可以是接收先前狀態值並返回新狀態值的回呼函數。 + +這有什麼影響?這意味著如果您想在任何 `on[State]Change` 回呼中添加一些額外邏輯,您可以這樣做,但您需要檢查新的更新器值是函數還是值。 + +這就是為什麼我們在上面的 `setState` 函數中有 `updater instanceof Function` 檢查。此檢查允許我們在同一函數中處理原始值和回呼函數。 + +### 狀態類型 + +TanStack Table 中的所有複雜狀態都有自己的 TypeScript 類型,您可以導入和使用。這對於確保您為控制的狀態值使用正確的資料結構和屬性非常有用。 + +```tsx +import { useVueTable, type SortingState } from '@tanstack/vue-table' +//... +const sorting = ref([ + { + id: 'age', //您應該可以自動完成 `id` 和 `desc` 屬性 + desc: true, + } +]) +``` diff --git a/docs/zh-hant/framework/vue/vue-table.md b/docs/zh-hant/framework/vue/vue-table.md new file mode 100644 index 0000000000..298a7e1a79 --- /dev/null +++ b/docs/zh-hant/framework/vue/vue-table.md @@ -0,0 +1,48 @@ +--- +source-updated-at: '2024-05-17T05:10:48.000Z' +translation-updated-at: '2025-05-08T23:42:11.042Z' +title: Vue 表格適配器 +--- +Vue Table + +TanStack Table 的核心是 **框架無關 (framework agnostic)** 的,這意味著無論您使用哪種框架,其 API 都保持一致。根據您使用的框架,我們提供了適配器 (adapters) 來簡化與表格核心的互動。請參閱「適配器」選單以查看可用的適配器。 + +`@tanstack/vue-table` 適配器是對核心表格邏輯的封裝。其主要工作是依照 "Vue" 的方式管理狀態,並提供類型以及單元格/表頭/表尾模板的渲染實現。 + +## 匯出項目 + +`@tanstack/vue-table` 重新匯出了 `@tanstack/table-core` 的所有 API 以及以下內容: + +### `useVueTable` + +接收一個 `options` 物件並回傳一個表格實例。 + +```ts +import { useVueTable } from '@tanstack/vue-table' + +const table = useVueTable(options) +// ...渲染您的表格 +``` + +### `FlexRender` + +一個 Vue 元件,用於渲染帶有動態值的單元格/表頭/表尾模板。 + +範例: + +```vue +import { FlexRender } from '@tanstack/vue-table' + + +``` diff --git a/docs/zh-hant/guide/cells.md b/docs/zh-hant/guide/cells.md new file mode 100644 index 0000000000..65781db500 --- /dev/null +++ b/docs/zh-hant/guide/cells.md @@ -0,0 +1,87 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:42:22.632Z' +title: 儲存格 +--- +## API + +[Cell API](../api/core/cell) + +## Cells 指南 + +本快速指南將討論在 TanStack Table 中獲取及與 `cell` 物件互動的不同方式。 + +### 從何處獲取 Cells + +Cells 來自 [Rows](../guide/rows)。這樣說就夠清楚了吧? + +根據您使用的功能,有多種 `row` 實例 API 可用於從行中獲取對應的 cells。最常見的是使用 `row.getAllCells` 或 `row.getVisibleCells` API(如果您使用欄位可見性功能),但也有其他類似的 API 可供使用。 + +### Cell 物件 + +每個 cell 物件都可以與 UI 中的 `` 或類似單元格元素關聯。`cell` 物件上有幾個屬性和方法,可用於與表格狀態互動,並根據表格狀態提取單元格值。 + +#### Cell IDs + +每個 cell 物件都有一個 `id` 屬性,使其在表格實例中唯一。每個 `cell.id` 的結構簡單地是其父行和欄位 ID 的組合,並以下底線分隔。 + +```js +{ id: `${row.id}_${column.id}` } +``` + +在分組或聚合功能期間,`cell.id` 會附加額外的字串。 + +#### Cell 父物件 + +每個 cell 都儲存了對其父 [row](../guide/rows) 和 [column](../guide/columns) 物件的引用。 + +#### 存取 Cell 值 + +從 cell 存取資料值的推薦方式是使用 `cell.getValue` 或 `cell.renderValue` API。使用這些 API 會快取存取函數的結果,保持渲染效率。兩者唯一的區別是,`cell.renderValue` 會返回值或 `renderFallbackValue`(如果值為 undefined),而 `cell.getValue` 會返回值或 `undefined`(如果值為 undefined)。 + +> 注意:`cell.getValue` 和 `cell.renderValue` API 分別是 `row.getValue` 和 `row.renderValue` API 的快捷方式。 + +```js +// 從任何欄位存取資料 +const firstName = cell.getValue('firstName') // 從 firstName 欄位讀取 cell 值 +const renderedLastName = cell.renderValue('lastName') // 渲染 lastName 欄位的值 +``` + +#### 從任何 Cell 存取其他行資料 + +由於每個 cell 物件都與其父行關聯,您可以使用 `cell.row.original` 存取表格中使用的原始行的任何資料。 + +```js +// 即使我們處於不同 cell 的作用域中,仍可存取原始行資料 +const firstName = cell.row.original.firstName // { firstName: 'John', lastName: 'Doe' } +``` + +### 更多 Cell API + +根據您為表格使用的功能,還有數十個其他有用的 API 可與 cells 互動。詳情請參閱各功能的 API 文件或指南。 + +### Cell 渲染 + +您可以直接使用 `cell.renderValue` 或 `cell.getValue` API 來渲染表格的 cells。然而,這些 API 僅會輸出原始 cell 值(來自存取函數)。如果您使用 `cell: () => JSX` 欄位定義選項,則需要使用來自適配器的 `flexRender` API 工具。 + +使用 `flexRender` API 將允許 cell 正確渲染任何額外的標記或 JSX,並以正確的參數呼叫回調函數。 + +```jsx +import { flexRender } from '@tanstack/react-table' + +const columns = [ + { + accessorKey: 'fullName', + cell: ({ cell, row }) => { + return
{row.original.firstName} {row.original.lastName}
+ } + //... + } +] +//... + + {row.getVisibleCells().map(cell => { + return {flexRender(cell.column.columnDef.cell, cell.getContext())} + })} + +``` diff --git a/docs/zh-hant/guide/column-defs.md b/docs/zh-hant/guide/column-defs.md new file mode 100644 index 0000000000..e5e1dd511c --- /dev/null +++ b/docs/zh-hant/guide/column-defs.md @@ -0,0 +1,283 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:03.765Z' +title: 欄位定義 +--- +## API + +[欄位定義](../api/core/column-def) + +## 欄位定義指南 + +> 注意:本指南是關於為表格設定欄位定義,而非關於表格實例中實際生成的 [`column`](../guide/columns) 物件。 + +欄位定義是構建表格最重要的部分。它們負責: + +- 建立將用於排序、篩選、分組等所有功能的底層資料模型 +- 將資料模型格式化為表格中顯示的內容 +- 建立 [標題群組](../api/core/header-group)、[標題](../api/core/header) 和 [頁尾](../api/core/column-def#footer) +- 建立僅用於顯示的欄位,例如操作按鈕、核取方塊、展開器、走勢圖等 + +## 欄位定義類型 + +以下「類型」的欄位定義並非實際的 TypeScript 類型,而是用來描述欄位定義的整體分類: + +- `存取器欄位 (Accessor Columns)` + - 存取器欄位具有底層資料模型,因此可以進行排序、篩選、分組等操作 +- `顯示欄位 (Display Columns)` + - 顯示欄位**沒有**資料模型,因此無法排序、篩選等,但可用於在表格中顯示任意內容,例如行操作按鈕、核取方塊、展開器等 +- `分組欄位 (Grouping Columns)` + - 分組欄位**沒有**資料模型,因此也無法排序、篩選等,主要用於將其他欄位分組。通常會為欄位群組定義標題或頁尾 + +## 欄位輔助工具 + +雖然欄位定義最終只是普通物件,但表格核心提供了一個 `createColumnHelper` 函式,當傳入行類型時,會返回一個用於以最高類型安全性建立不同欄位定義類型的工具。 + +以下是建立和使用欄位輔助工具的範例: + +```tsx +// 定義你的行結構 +type Person = { + firstName: string + lastName: string + age: number + visits: number + status: string + progress: number +} + +const columnHelper = createColumnHelper() + +// 建立一些欄位! +const defaultColumns = [ + // 顯示欄位 + columnHelper.display({ + id: 'actions', + cell: props => , + }), + // 分組欄位 + columnHelper.group({ + header: 'Name', + footer: props => props.column.id, + columns: [ + // 存取器欄位 + columnHelper.accessor('firstName', { + cell: info => info.getValue(), + footer: props => props.column.id, + }), + // 存取器欄位 + columnHelper.accessor(row => row.lastName, { + id: 'lastName', + cell: info => info.getValue(), + header: () => Last Name, + footer: props => props.column.id, + }), + ], + }), + // 分組欄位 + columnHelper.group({ + header: 'Info', + footer: props => props.column.id, + columns: [ + // 存取器欄位 + columnHelper.accessor('age', { + header: () => 'Age', + footer: props => props.column.id, + }), + // 分組欄位 + columnHelper.group({ + header: 'More Info', + columns: [ + // 存取器欄位 + columnHelper.accessor('visits', { + header: () => Visits, + footer: props => props.column.id, + }), + // 存取器欄位 + columnHelper.accessor('status', { + header: 'Status', + footer: props => props.column.id, + }), + // 存取器欄位 + columnHelper.accessor('progress', { + header: 'Profile Progress', + footer: props => props.column.id, + }), + ], + }), + ], + }), +] +``` + +## 建立存取器欄位 + +資料欄位的獨特之處在於必須配置為從 `data` 陣列中的每個項目提取原始值。 + +有三種方法可以做到這一點: + +- 如果你的項目是 `物件`,使用對應於你想提取值的物件鍵 +- 如果你的項目是巢狀 `陣列`,使用對應於你想提取值的陣列索引 +- 使用返回你想提取值的存取器函式 + +## 物件鍵 + +如果你的每個項目是具有以下結構的物件: + +```tsx +type Person = { + firstName: string + lastName: string + age: number + visits: number + status: string + progress: number +} +``` + +你可以這樣提取 `firstName` 值: + +```tsx +columnHelper.accessor('firstName') + +// 或 + +{ + accessorKey: 'firstName', +} +``` + +## 深層鍵 + +如果你的每個項目是具有以下結構的物件: + +```tsx +type Person = { + name: { + first: string + last: string + } + info: { + age: number + visits: number + } +} +``` + +你可以這樣提取 `first` 值: + +```tsx +columnHelper.accessor('name.first', { + id: 'firstName', +}) + +// 或 + +{ + accessorKey: 'name.first', + id: 'firstName', +} +``` + +## 陣列索引 + +如果你的每個項目是具有以下結構的陣列: + +```tsx +type Sales = [Date, number] +``` + +你可以這樣提取 `number` 值: + +```tsx +columnHelper.accessor(1) + +// 或 + +{ + accessorKey: 1, +} +``` + +## 存取器函式 + +如果你的每個項目是具有以下結構的物件: + +```tsx +type Person = { + firstName: string + lastName: string + age: number + visits: number + status: string + progress: number +} +``` + +你可以這樣提取計算後的全名值: + +```tsx +columnHelper.accessor(row => `${row.firstName} ${row.lastName}`, { + id: 'fullName', +}) + +// 或 + +{ + id: 'fullName', + accessorFn: row => `${row.firstName} ${row.lastName}`, +} +``` + +> 🧠 記住,存取的值是用於排序、篩選等的,因此你需要確保存取器函式返回一個可以有意義操作的原始值。如果返回非原始值(如物件或陣列),則需要適當的篩選/排序/分組函式來操作它們,甚至可能需要提供自己的函式!😬 + +## 唯一欄位 ID + +欄位通過以下三種策略唯一標識: + +- 如果使用物件鍵或陣列索引定義存取器欄位,則相同的鍵或索引將用於唯一標識欄位 + - 物件鍵中的任何句點 (`.`) 將被替換為底線 (`_`) +- 如果使用存取器函式定義存取器欄位 + - 欄位的 `id` 屬性將用於唯一標識欄位,或 + - 如果提供了原始 `字串` 標題,則該標題字串將用於唯一標識欄位 + +> 🧠 簡單記住:如果使用存取器函式定義欄位,請提供字串標題或唯一的 `id` 屬性 + +## 欄位格式化與渲染 + +預設情況下,欄位單元格會將其資料模型值顯示為字串。你可以通過提供自訂渲染實現來覆蓋此行為。每個實現都會獲得有關單元格、標題或頁尾的相關資訊,並返回你的框架適配器可以渲染的內容,例如 JSX/元件/字串等。這取決於你使用的適配器。 + +有幾種格式化器可供使用: + +- `cell`:用於格式化單元格 +- `aggregatedCell`:用於在聚合時格式化單元格 +- `header`:用於格式化標題 +- `footer`:用於格式化頁尾 + +## 單元格格式化 + +你可以通過將函式傳遞給 `cell` 屬性並使用 `props.getValue()` 函式來存取單元格的值,從而提供自訂單元格格式化器: + +```tsx +columnHelper.accessor('firstName', { + cell: props => {props.getValue().toUpperCase()}, +}) +``` + +單元格格式化器還提供了 `row` 和 `table` 物件,允許你不僅基於單元格值來自訂單元格格式化。以下範例提供了 `firstName` 作為存取器,但同時顯示了位於原始行物件上的前置使用者 ID: + +```tsx +columnHelper.accessor('firstName', { + cell: props => ( + {`${props.row.original.id} - ${props.getValue()}`} + ), +}) +``` + +## 聚合單元格格式化 + +有關聚合單元格的更多資訊,請參閱 [分組](../guide/grouping) + +## 標題與頁尾格式化 + +標題和頁尾無法存取行資料,但仍使用相同的概念來顯示自訂內容 diff --git a/docs/zh-hant/guide/column-faceting.md b/docs/zh-hant/guide/column-faceting.md new file mode 100644 index 0000000000..eddc4031b3 --- /dev/null +++ b/docs/zh-hant/guide/column-faceting.md @@ -0,0 +1,90 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:54.595Z' +title: 欄位面向 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [filters-faceted](../framework/react/examples/filters-faceted) + +## API + +[欄位切面 API](../api/features/column-faceting) + +## 欄位切面指南 + +欄位切面 (Column Faceting) 是一項功能,允許您從欄位資料中為指定欄位生成值列表。例如,可以從欄位所有列中生成唯一值列表,用作自動完成篩選元件的搜尋建議;或是從數字欄位中生成最小值和最大值的元組,用作範圍滑桿篩選元件的範圍設定。 + +### 欄位切面行模型 + +若要使用任何欄位切面功能,您必須在表格選項中包含適當的行模型。 + +```ts +//只需導入您需要的行模型 +import { + getCoreRowModel, + getFacetedRowModel, + getFacetedMinMaxValues, //依賴 getFacetedRowModel + getFacetedUniqueValues, //依賴 getFacetedRowModel +} +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getFacetedRowModel: getFacetedRowModel(), //如果需要為欄位生成值列表(其他切面行模型依賴此模型) + getFacetedMinMaxValues: getFacetedMinMaxValues(), //如果需要最小/最大值 + getFacetedUniqueValues: getFacetedUniqueValues(), //如果需要唯一值列表 + //... +}) +``` + +首先,您必須包含 `getFacetedRowModel` 行模型。此模型會為指定欄位生成值列表。如果需要唯一值列表,請包含 `getFacetedUniqueValues` 行模型;如果需要最小值和最大值的元組,請包含 `getFacetedMinMaxValues` 行模型。 + +### 使用切面行模型 + +在表格選項中包含適當的行模型後,您就能使用切面欄位實例 API 來存取由切面行模型生成的值列表。 + +```ts +// 用於自動完成篩選的唯一值列表 +const autoCompleteSuggestions = + Array.from(column.getFacetedUniqueValues().keys()) + .sort() + .slice(0, 5000); +``` + +```ts +// 用於範圍篩選的最小最大值元組 +const [min, max] = column.getFacetedMinMaxValues() ?? [0, 1]; +``` + +### 自訂(伺服器端)切面 + +如果不使用內建的客戶端切面功能,您可以在伺服器端實作自己的切面邏輯,並將切面值傳遞至客戶端。您可以使用 `getFacetedUniqueValues` 和 `getFacetedMinMaxValues` 表格選項來解析來自伺服器端的切面值。 + +```ts +const facetingQuery = useQuery( + //... +) + +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getFacetedRowModel: getFacetedRowModel(), + getFacetedUniqueValues: (table, columnId) => { + const uniqueValueMap = new Map(); + //... + return uniqueValueMap; + }, + getFacetedMinMaxValues: (table, columnId) => { + //... + return [min, max]; + }, + //... +}) +``` + +或者,您也可以完全不透過 TanStack Table API 來處理任何切面邏輯。只需直接獲取您的列表並將其傳遞給篩選元件即可。 diff --git a/docs/zh-hant/guide/column-filtering.md b/docs/zh-hant/guide/column-filtering.md new file mode 100644 index 0000000000..8f78c7b1f8 --- /dev/null +++ b/docs/zh-hant/guide/column-filtering.md @@ -0,0 +1,338 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:28.651Z' +title: 欄位過濾 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [欄位過濾](../framework/react/examples/filters) +- [多面過濾](../framework/react/examples/filters-faceted) (自動完成與範圍過濾) +- [模糊搜尋](../framework/react/examples/filters-fuzzy) (Match Sorter) +- [可編輯資料](../framework/react/examples/editable-data) +- [展開功能](../framework/react/examples/expanding) (從子列過濾) +- [群組功能](../framework/react/examples/grouping) +- [分頁功能](../framework/react/examples/pagination) +- [列選取](../framework/react/examples/row-selection) + +## API + +[欄位過濾 API](../api/features/column-filtering) + +## 欄位過濾指南 + +過濾功能分為兩種:欄位過濾 (Column Filtering) 與全域過濾 (Global Filtering)。 + +本指南將專注於欄位過濾,這是針對單一欄位存取值 (accessor value) 所應用的過濾方式。 + +TanStack Table 同時支援客戶端 (client-side) 與手動伺服器端 (manual server-side) 過濾。本指南將說明如何實作與自訂這兩種方式,並協助您決定哪種最適合您的使用情境。 + +### 客戶端 vs 伺服器端過濾 + +如果您有大型資料集,可能不希望將所有資料載入客戶端瀏覽器進行過濾。在這種情況下,您很可能需要實作伺服器端過濾、排序、分頁等功能。 + +然而,如同在[分頁指南](../guide/pagination#should-you-use-client-side-pagination)中討論的,許多開發者低估了客戶端能處理的資料量而不影響效能。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(), // 手動伺服器端過濾不需要此選項 + 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(), // 客戶端過濾需要此選項 +}) +``` + +### 欄位過濾狀態 + +無論您使用客戶端或伺服器端過濾,都可以利用 TanStack Table 提供的內建欄位過濾狀態管理功能。有許多表格和欄位 API 可用於變更和互動過濾狀態,以及獲取欄位過濾狀態。 + +欄位過濾狀態定義為具有以下結構的物件陣列: + +```ts +interface ColumnFilter { + id: string + value: unknown +} +type ColumnFiltersState = ColumnFilter[] +``` + +由於欄位過濾狀態是物件陣列,您可以同時應用多個欄位過濾。 + +#### 存取欄位過濾狀態 + +您可以像其他表格狀態一樣,透過 `table.getState()` API 從表格實例存取欄位過濾狀態。 + +```jsx +const table = useReactTable({ + columns, + data, + //... +}) + +console.log(table.getState().columnFilters) // 從表格實例存取欄位過濾狀態 +``` + +不過,如果您需要在表格初始化前存取欄位過濾狀態,可以像下方所示「控制」欄位過濾狀態。 + +### 受控欄位過濾狀態 + +如果需要輕鬆存取欄位過濾狀態,您可以使用 `state.columnFilters` 和 `onColumnFiltersChange` 表格選項,在自己的狀態管理中控制/管理欄位過濾狀態。 + +```tsx +const [columnFilters, setColumnFilters] = useState([]) // 可在此設定初始欄位過濾狀態 +//... +const table = useReactTable({ + columns, + data, + //... + state: { + columnFilters, + }, + onColumnFiltersChange: setColumnFilters, +}) +``` + +#### 初始欄位過濾狀態 + +如果不需要在自己的狀態管理或作用域中控制欄位過濾狀態,但仍想設定初始欄位過濾狀態,可以使用 `initialState` 表格選項而非 `state`。 + +```jsx +const table = useReactTable({ + columns, + data, + //... + initialState: { + columnFilters: [ + { + id: 'name', + value: 'John', // 預設以 'John' 過濾名稱欄位 + }, + ], + }, +}) +``` + +> **注意**:請勿同時使用 `initialState.columnFilters` 和 `state.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 +``` + +每個過濾函式會接收: + +- 要過濾的列 +- 用於獲取列值的欄位 ID +- 過濾值 + +並應返回 `true` 表示該列應包含在過濾結果中,`false` 則表示應移除。 + +```jsx +const columns = [ + { + header: () => 'Name', + accessorKey: 'name', + filterFn: 'includesString', // 使用內建過濾函式 + }, + { + header: () => 'Age', + accessorKey: 'age', + filterFn: 'inNumberRange', + }, + { + header: () => 'Birthday', + accessorKey: 'birthday', + filterFn: 'myCustomFilterFn', // 使用自訂全域過濾函式 + }, + { + header: () => 'Profile', + accessorKey: 'profile', + // 直接使用自訂過濾函式 + filterFn: (row, columnId, filterValue) => { + return // 根據自訂邏輯返回 true 或 false + }, + } +] +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + filterFns: { // 新增自訂全域過濾函式 + myCustomFilterFn: (row, columnId, filterValue) => { // 在此內聯定義 + return // 根據自訂邏輯返回 true 或 false + }, + startsWith: startsWithFilterFn, // 在其他地方定義 + }, +}) +``` + +##### 自訂過濾函式行為 + +您可以為過濾函式附加一些其他屬性來自訂其行為: + +- `filterFn.resolveFilterValue` - 此選用「掛載」方法允許過濾函式在傳遞給過濾函式前,轉換/清理/格式化過濾值。 + +- `filterFn.autoRemove` - 此選用「掛載」方法會接收過濾值,並預期返回 `true` 表示該過濾值應從過濾狀態中移除。例如,某些布林型過濾可能希望在過濾值設為 `false` 時,將其從表格狀態中移除。 + +```tsx +const startsWithFilterFn = ( + row: Row, + columnId: string, + filterValue: number | string, //resolveFilterValue 會將其轉換為字串 +) => + row + .getValue(columnId) + .toString() + .toLowerCase() + .trim() + .startsWith(filterValue); // 在 `resolveFilterValue` 中對過濾值進行 toString、toLowerCase 和 trim 處理 + +// 如果過濾值為假值(此例為空字串),則從過濾狀態中移除 +startsWithFilterFn.autoRemove = (val: any) => !val; + +// 在傳遞給過濾函式前,轉換/清理/格式化過濾值 +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, // 停用此欄位的過濾功能 + }, + //... +] +//... +const table = useReactTable({ + columns, + data, + enableColumnFilters: false, // 停用所有欄位的過濾功能 +}) +``` + +#### 過濾子列 (展開功能) + +在使用展開、群組和聚合等功能時,有幾個額外的表格選項可自訂欄位過濾行為。 + +##### 從葉子列過濾 + +預設情況下,過濾是從父列向下進行的,因此如果父列被過濾掉,其所有子列也會被過濾掉。根據您的使用情境,如果只希望使用者搜尋頂層列而非子列,這可能是理想行為。這也是效能最佳的選項。 + +然而,如果您希望允許過濾和搜尋子列,無論父列是否被過濾掉,可以將 `filterFromLeafRows` 表格選項設為 `true`。設為 `true` 會使過濾從葉子列向上進行,這意味著只要有一個子列或孫子列被包含,父列也會被包含。 + +```jsx +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getExpandedRowModel: getExpandedRowModel(), + filterFromLeafRows: true, // 過濾和搜尋子列 +}) +``` + +##### 最大葉子列過濾深度 + +預設情況下,過濾會套用至樹中的所有列,無論它們是根層級的父列還是父列的子葉子列。將 `maxLeafRowFilterDepth` 表格選項設為 `0` 會使過濾僅套用至根層級的父列,所有子列保持未過濾狀態。類似地,設為 `1` 會使過濾僅套用至一層深的子葉子列,依此類推。 + +如果您希望在父列通過過濾時保留其子列不被過濾掉,請使用 `maxLeafRowFilterDepth: 0`。 + +```jsx +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getExpandedRowModel: getExpandedRowModel(), + maxLeafRowFilterDepth: 0, // 僅過濾根層級的父列 +}) +``` + +### 欄位過濾 API + +有許多欄位和表格 API 可用於與欄位過濾狀態互動並連結至您的 UI 元件。以下是可用 API 及其最常見用途的清單: + +- `table.setColumnFilters` - 以新狀態覆寫整個欄位過濾狀態。 +- `table.resetColumnFilters` - 適用於「清除所有/重設過濾」按鈕。 + +- **`column.getFilterValue`** - 適用於獲取輸入的預設初始過濾值,或直接提供過濾值給過濾輸入。 +- **`column.setFilterValue`** - 適用於將過濾輸入連結至其 `onChange` 或 `onBlur` 處理器。 + +- `column.getCanFilter` - 適用於停用/啟用過濾輸入。 +- `column.getIsFiltered` - 適用於顯示欄位目前正在過濾的視覺指示器。 +- `column.getFilterIndex` - 適用於顯示目前過濾應用的順序。 + +- `column.getAutoFilterFn` - 內部用於在未指定時尋找欄位的預設過濾函式。 +- `column.getFilterFn` - 適用於顯示目前使用的過濾模式或函式。 diff --git a/docs/zh-hant/guide/column-ordering.md b/docs/zh-hant/guide/column-ordering.md new file mode 100644 index 0000000000..e532745b32 --- /dev/null +++ b/docs/zh-hant/guide/column-ordering.md @@ -0,0 +1,112 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:42:10.842Z' +title: 欄位排序 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [column-ordering](../framework/react/examples/column-ordering) +- [column-dnd](../framework/react/examples/column-dnd) + +## API + +[欄位排序 API](../api/features/column-ordering) + +## 欄位排序指南 + +預設情況下,欄位會按照 `columns` 陣列中定義的順序排列。然而,您可以使用 `columnOrder` 狀態手動指定欄位順序。其他功能如欄位固定 (pinning) 和分組 (grouping) 也會影響欄位排序。 + +### 影響欄位排序的因素 + +共有 3 種表格功能會重新排序欄位,其執行順序如下: + +1. [欄位固定 (Column Pinning)](../guide/column-pinning) - 若啟用固定功能,欄位會被拆分為左側、中間 (未固定) 和右側固定的欄位。 +2. 手動 **欄位排序** - 套用手動指定的欄位順序。 +3. [分組 (Grouping)](../guide/grouping) - 若啟用分組功能、分組狀態為啟用,且 `tableOptions.groupedColumnMode` 設為 `'reorder' | 'remove'`,則分組欄位會被重新排序至欄位流的最前面。 + +> **注意:** 若與欄位固定功能同時使用,`columnOrder` 狀態僅會影響未固定的欄位。 + +### 欄位排序狀態 + +若未提供 `columnOrder` 狀態,TanStack Table 將直接使用 `columns` 陣列中的欄位順序。但您可以提供一個包含字串欄位 ID 的陣列給 `columnOrder` 狀態來指定欄位順序。 + +#### 預設欄位順序 + +若只需指定初始欄位順序,可直接在 `initialState` 表格選項中設定 `columnOrder` 狀態。 + +```jsx +const table = useReactTable({ + //... + initialState: { + columnOrder: ['columnId1', 'columnId2', 'columnId3'], + } + //... +}); +``` + +> **注意:** 若同時使用 `state` 表格選項來指定 `columnOrder` 狀態,`initialState` 將不會生效。請僅在 `initialState` 或 `state` 其中一處指定特定狀態,不要兩者都指定。 + +#### 管理欄位排序狀態 + +若需動態變更欄位順序,或在表格初始化後設定欄位順序,可以像管理其他表格狀態一樣管理 `columnOrder` 狀態。 + +```jsx +const [columnOrder, setColumnOrder] = useState(['columnId1', 'columnId2', 'columnId3']); //可選擇初始化欄位順序 +//... +const table = useReactTable({ + //... + state: { + columnOrder, + //... + } + onColumnOrderChange: setColumnOrder, + //... +}); +``` + +### 重新排序欄位 + +若表格提供允許使用者重新排序欄位的 UI,可以按照以下方式設定邏輯: + +```tsx +const [columnOrder, setColumnOrder] = useState(columns.map(c => c.id)); + +//根據選擇的拖放 (dnd) 解決方案,您可能需要或不需要此類狀態 +const [movingColumnId, setMovingColumnId] = useState(null); +const [targetColumnId, setTargetColumnId] = useState(null); + +//用於拼接和重新排序 columnOrder 陣列的實用函數 +const reorderColumn = ( + movingColumnId: Column, + targetColumnId: Column, +): string[] => { + const newColumnOrder = [...columnOrder]; + newColumnOrder.splice( + newColumnOrder.indexOf(targetColumnId), + 0, + newColumnOrder.splice(newColumnOrder.indexOf(movingColumnId), 1)[0], + ); + setColumnOrder(newColumnOrder); +}; + +const handleDragEnd = (e: DragEvent) => { + if(!movingColumnId || !targetColumnId) return; + setColumnOrder(reorderColumn(movingColumnId, targetColumnId)); +}; + +//使用您選擇的拖放解決方案 +``` + +#### 拖放欄位重新排序建議 (React) + +實作拖放功能與 TanStack Table 搭配使用的方式無疑有許多種。以下是幾項建議,以避免遇到問題: + +1. **不要** 嘗試使用 [`"react-dnd"`](https://react-dnd.github.io/react-dnd/docs/overview) _若您使用的是 React 18 或更新版本_。React DnD 在其時代是一個重要的函式庫,但現在更新頻率較低,且與 React 18 存在不相容問題,特別是在 React Strict Mode 中。雖然仍有可能使其運作,但有更新且更活躍維護的替代方案,相容性更好。React DnD 的 Provider 也可能干擾或與您應用中其他拖放解決方案衝突。 + +2. 使用 [`"@dnd-kit/core"`](https://dndkit.com/)。DnD Kit 是一個現代化、模組化且輕量的拖放函式庫,與現代 React 生態系統高度相容,且能良好支援語意化的 `` 標記。官方 TanStack 拖放範例 [Column DnD](../framework/react/examples/column-dnd) 和 [Row DnD](../framework/react/examples/row-dnd) 現在都使用 DnD Kit。 + +3. 考慮其他拖放函式庫如 [`"react-beautiful-dnd"`](https://github.com/atlassian/react-beautiful-dnd),但需注意其可能較大的套件體積、維護狀態以及與 `
` 標記的相容性。 + +4. 考慮使用原生瀏覽器事件和狀態管理來實作輕量的拖放功能。但需注意,若未額外實作適當的觸控事件,此方法可能對行動裝置使用者不夠友善。[Material React Table V2](https://www.material-react-table.com/docs/examples/column-ordering) 是一個僅使用瀏覽器拖放事件 (如 `onDragStart`、`onDragEnd`、`onDragEnter`) 且無其他依賴的 TanStack Table 實作範例。可瀏覽其原始碼了解實作方式。 diff --git a/docs/zh-hant/guide/column-pinning.md b/docs/zh-hant/guide/column-pinning.md new file mode 100644 index 0000000000..89613d2fb4 --- /dev/null +++ b/docs/zh-hant/guide/column-pinning.md @@ -0,0 +1,93 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:53.594Z' +title: 欄位固定 +--- +## 範例 + +想要直接查看實作方式嗎?請參考以下範例: + +- [column-pinning](../framework/react/examples/column-pinning) +- [sticky-column-pinning](../framework/react/examples/column-pinning-sticky) + +### 其他範例 + +- [Svelte column-pinning](../framework/svelte/examples/column-pinning) +- [Vue column-pinning](../framework/vue/examples/column-pinning) + +## API + +[欄位釘選 API](../api/features/column-pinning) + +## 欄位釘選指南 + +TanStack Table 提供了有助於在表格 UI 中實作欄位釘選功能的狀態和 API。你可以透過多種方式實作欄位釘選。你可以將釘選的欄位拆分到獨立的表格中,或是保持所有欄位在同一個表格內,但使用釘選狀態來正確排序欄位,並使用 sticky CSS 將欄位釘選在左側或右側。 + +### 欄位釘選如何影響欄位順序 + +有三種表格功能會影響欄位順序,其執行順序如下: + +1. **欄位釘選** - 若啟用釘選,欄位會被拆分為左側、中間(未釘選)和右側釘選的欄位。 +2. 手動[欄位排序](../guide/column-ordering) - 套用手動指定的欄位順序。 +3. [群組](../guide/grouping) - 若啟用群組功能、有活躍的群組狀態,且 `tableOptions.groupedColumnMode` 設為 `'reorder' | 'remove'`,則群組欄位會被重新排序至欄位流的最前面。 + +改變釘選欄位順序的唯一方式是透過 `columnPinning.left` 和 `columnPinning.right` 狀態本身。`columnOrder` 狀態僅會影響未釘選(「中間」)欄位的順序。 + +### 欄位釘選狀態 + +管理 `columnPinning` 狀態是可選的,通常不需要除非你正在新增持久狀態功能。TanStack Table 已經會為你追蹤欄位釘選狀態。如有需要,可以像管理其他表格狀態一樣管理 `columnPinning` 狀態。 + +```jsx +const [columnPinning, setColumnPinning] = useState({ + left: [], + right: [], +}); +//... +const table = useReactTable({ + //... + state: { + columnPinning, + //... + } + onColumnPinningChange: setColumnPinning, + //... +}); +``` + +### 預設釘選欄位 + +一個非常常見的使用情境是預設釘選某些欄位。你可以透過初始化 `columnPinning` 狀態時指定釘選的 columnIds,或是使用 `initialState` 表格選項來達成。 + +```jsx +const table = useReactTable({ + //... + initialState: { + columnPinning: { + left: ['expand-column'], + right: ['actions-column'], + }, + //... + } + //... +}); +``` + +### 實用的欄位釘選 API + +> 注意:部分 API 是 v8.12.0 新增的 + +以下是一些有助於實作欄位釘選功能的實用欄位 API 方法: + +- [`column.getCanPin`](../api/features/column-pinning#getcanpin):用於判斷欄位是否可被釘選。 +- [`column.pin`](../api/features/column-pinning#pin):用於將欄位釘選至左側或右側,或用於取消釘選。 +- [`column.getIsPinned`](../api/features/column-pinning#getispinned):用於判斷欄位被釘選的位置。 +- [`column.getStart`](../api/features/column-pinning#getstart):用於提供釘選欄位正確的 `left` CSS 值。 +- [`column.getAfter`](../api/features/column-pinning#getafter):用於提供釘選欄位正確的 `right` CSS 值。 +- [`column.getIsLastColumn`](../api/features/column-pinning#getislastcolumn):用於判斷欄位是否為其釘選群組中的最後一個欄位。適用於新增 box-shadow。 +- [`column.getIsFirstColumn`](../api/features/column-pinning#getisfirstcolumn):用於判斷欄位是否為其釘選群組中的第一個欄位。適用於新增 box-shadow。 + +### 拆分表格的欄位釘選 + +如果你僅使用 sticky CSS 來釘選欄位,大部分情況下可以像平常一樣使用 `table.getHeaderGroups` 和 `row.getVisibleCells` 方法來渲染表格。 + +然而,如果你將釘選欄位拆分到獨立的表格中,可以使用 `table.getLeftHeaderGroups`、`table.getCenterHeaderGroups`、`table.getRightHeaderGroups`、`row.getLeftVisibleCells`、`row.getCenterVisibleCells` 和 `row.getRightVisibleCells` 方法,僅渲染與當前表格相關的欄位。 diff --git a/docs/zh-hant/guide/column-sizing.md b/docs/zh-hant/guide/column-sizing.md new file mode 100644 index 0000000000..e71499855d --- /dev/null +++ b/docs/zh-hant/guide/column-sizing.md @@ -0,0 +1,178 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:42:14.279Z' +title: 欄位調整大小 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [column-sizing](../framework/react/examples/column-sizing) +- [column-resizing-performant](../framework/react/examples/column-resizing-performant) + +## API + +[欄位尺寸調整 API](../api/features/column-sizing) + +## 欄位尺寸調整指南 + +欄位尺寸調整功能允許您選擇性地指定每個欄位的寬度,包括最小和最大寬度。同時也讓您和使用者能動態調整所有欄位的寬度,例如透過拖曳欄位標頭來實現。 + +### 欄位寬度 + +預設情況下,欄位會套用以下測量選項: + +```tsx +export const defaultColumnSizing = { + size: 150, + minSize: 20, + maxSize: Number.MAX_SAFE_INTEGER, +} +``` + +這些預設值可以透過 `tableOptions.defaultColumn` 和個別欄位定義來覆寫,優先順序如前述順序。 + +```tsx +const columns = [ + { + accessorKey: 'col1', + size: 270, //為此欄位設定尺寸 + }, + //... +] + +const table = useReactTable({ + //覆寫預設欄位尺寸 + defaultColumn: { + size: 200, //起始欄位尺寸 + minSize: 50, //在欄位調整時強制執行 + maxSize: 500, //在欄位調整時強制執行 + }, +}) +``` + +欄位的「尺寸」在表格狀態中以數字形式儲存,通常會被解讀為像素單位值,但您可以根據需求將這些欄位尺寸值掛接到您的 CSS 樣式中。 + +作為一個無頭工具 (headless utility),表格的欄位尺寸邏輯實際上只是一組狀態集合,您可以根據需求應用到自己的佈局中(我們的範例實作了兩種此邏輯的樣式)。您可以透過多種方式應用這些寬度測量: + +- 語意化的 `table` 元素或任何以表格 CSS 模式顯示的元素 +- `div/span` 元素或任何以非表格 CSS 模式顯示的元素 + - 具有固定寬度的區塊層級元素 + - 具有固定寬度的絕對定位元素 + - 具有彈性寬度的 Flexbox 定位元素 + - 具有彈性寬度的 Grid 定位元素 +- 實際上任何能將單元格寬度內插到表格結構中的佈局機制 + +每種方法都有其權衡和限制,這些通常是 UI/元件函式庫或設計系統的觀點,幸運的是您不需要擔心這些 😉。 + +### 欄位調整大小 + +TanStack Table 提供內建的欄位調整大小狀態和 API,讓您可以輕鬆在表格 UI 中實作欄位調整大小功能,並提供多種 UX 和效能選項。 + +#### 啟用欄位調整大小 + +預設情況下,`column.getCanResize()` API 會對所有欄位回傳 `true`,但您可以透過 `enableColumnResizing` 表格選項禁用所有欄位的調整大小功能,或透過 `enableResizing` 欄位選項逐欄禁用。 + +```tsx +const columns = [ + { + accessorKey: 'id', + enableResizing: false, //僅對此欄位禁用調整大小 + size: 200, //起始欄位尺寸 + }, + //... +] +``` + +#### 欄位調整模式 + +預設情況下,欄位調整模式設為 `"onEnd"`。這表示 `column.getSize()` API 不會回傳新的欄位尺寸,直到使用者完成調整(拖曳)欄位。通常在調整欄位時會顯示一個小的 UI 指示器。 + +在 React TanStack Table 轉接器中,由於實現 60 fps 的欄位調整渲染可能較困難(取決於表格或網頁的複雜度),`"onEnd"` 欄位調整模式可以作為一個良好的預設選項,以避免使用者在調整欄位時出現卡頓或延遲。這並不是說您無法在使用 TanStack React Table 時實現 60 fps 的欄位調整渲染,但您可能需要進行額外的記憶化 (memoization) 或其他效能優化才能實現。 + +> 進階的欄位調整效能技巧將在[下方](#advanced-column-resizing-performance)討論。 + +如果您想將欄位調整模式改為 `"onChange"` 以實現即時的欄位調整渲染,可以透過 `columnResizeMode` 表格選項來設定。 + +```tsx +const table = useReactTable({ + //... + columnResizeMode: 'onChange', //將欄位調整模式改為 "onChange" +}) +``` + +#### 欄位調整方向 + +預設情況下,TanStack Table 假設表格標記語言 (markup) 是從左到右排列的。對於從右到左的佈局,您可能需要將欄位調整方向改為 `"rtl"`。 + +```tsx +const table = useReactTable({ + //... + columnResizeDirection: 'rtl', //針對特定地區設定將欄位調整方向改為 "rtl" +}) +``` + +#### 將欄位調整 API 連接到 UI + +有幾個非常方便的 API 可以讓您將欄位調整的拖曳互動連接到 UI。 + +##### 欄位尺寸 API + +要將欄位的尺寸應用到欄位標頭單元格、資料單元格或頁尾單元格,您可以使用以下 API: + +```ts +header.getSize() +column.getSize() +cell.column.getSize() +``` + +如何將這些尺寸樣式應用到您的標記語言 (markup) 取決於您,但通常會使用 CSS 變數或內聯樣式來應用欄位尺寸。 + +```tsx + +) +``` + +#### 必須這樣做嗎? + +這只是一種將自訂程式碼與 TanStack Table 內建功能整合的新方式。在上面的範例中,我們完全可以將 `density` 狀態儲存在 `React.useState` 中,在任何地方定義自己的 `toggleDensity` 處理函式,並在程式碼中獨立於表格實例使用它。在 TanStack Table 之外建立表格功能,而非深度整合到表格實例中,仍然是建立自訂功能的完全有效方式。根據你的使用情境,這可能不是擴展 TanStack Table 自訂功能的最簡潔方式。 diff --git a/docs/zh-hant/guide/data.md b/docs/zh-hant/guide/data.md new file mode 100644 index 0000000000..236ff11ee5 --- /dev/null +++ b/docs/zh-hant/guide/data.md @@ -0,0 +1,251 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:57.428Z' +title: 資料 +--- +## 資料指南 + +表格始於您的資料。您的欄位定義與資料列將取決於資料的結構。TanStack Table 提供了一些 TypeScript 功能,能協助您以類型安全的方式建立表格程式碼。若正確設定資料與類型,TanStack Table 將能推論資料結構,並確保欄位定義的正確性。 + +### TypeScript + +使用 TanStack Table 套件並不需要 TypeScript... ***但*** TanStack Table 的撰寫與組織方式,讓其出色的 TypeScript 體驗成為該函式庫的主要賣點之一。若未使用 TypeScript,您將錯失許多自動完成與類型檢查功能,這些功能既能加速開發,也能減少程式碼中的錯誤。 + +#### TypeScript 泛型 (Generics) + +基本了解 TypeScript 泛型及其運作方式,將有助於理解本指南,但您也能在過程中逐步掌握。官方 [TypeScript 泛型文件](https://www.typescriptlang.org/docs/handbook/2/generics.html) 對不熟悉 TypeScript 的人可能有所幫助。 + +### 定義資料類型 + +`data` 是一個物件陣列,將轉換為表格的資料列。陣列中的每個物件代表一列資料(一般情況下)。若使用 TypeScript,我們通常會為資料結構定義一個類型。此類型將作為其他表格、欄位、資料列與儲存格實例的泛型類型。在 TanStack Table 的類型與 API 中,此泛型通常稱為 `TData`。 + +例如,若有一個顯示使用者清單的表格,其資料陣列如下: + +```json +[ + { + "firstName": "Tanner", + "lastName": "Linsley", + "age": 33, + "visits": 100, + "progress": 50, + "status": "Married" + }, + { + "firstName": "Kevin", + "lastName": "Vandy", + "age": 27, + "visits": 200, + "progress": 100, + "status": "Single" + } +] +``` + +則我們可以定義一個使用者 (`TData`) 類型如下: + +```ts +//TData +type User = { + firstName: string + lastName: string + age: number + visits: number + progress: number + status: string +} +``` + +接著,我們可以用此類型定義 `data` 陣列,TanStack Table 將能智慧推論後續欄位、資料列、儲存格等的類型。這是因為 `data` 類型實際上就是 `TData` 泛型類型。傳遞給表格選項 `data` 的內容,將成為該表格實例的 `TData` 類型。只需確保後續定義欄位時,使用與 `data` 相同的 `TData` 類型。 + +```ts +//注意:data 需要一個「穩定」的參照,以避免無限重新渲染 +const data: User[] = [] +//或 +const [data, setData] = React.useState([]) +//或 +const data = ref([]) //vue +//等等... +``` + +#### 深層鍵值資料 + +若您的資料不是平整的物件陣列,也沒關係!定義欄位時,有策略可以存取深層巢狀資料。 + +若您的 `data` 如下所示: + +```json +[ + { + "name": { + "first": "Tanner", + "last": "Linsley" + }, + "info": { + "age": 33, + "visits": 100, + } + }, + { + "name": { + "first": "Kevin", + "last": "Vandy" + }, + "info": { + "age": 27, + "visits": 200, + } + } +] +``` + +您可以定義這樣的類型: + +```ts +type User = { + name: { + first: string + last: string + } + info: { + age: number + visits: number + } +} +``` + +並在欄位定義中,透過 `accessorKey` 的點記法或 `accessorFn` 存取資料。 + +```ts +const columns = [ + { + header: 'First Name', + accessorKey: 'name.first', + }, + { + header: 'Last Name', + accessorKey: 'name.last', + }, + { + header: 'Age', + accessorFn: row => row.info.age, + }, + //... +] +``` + +更詳細的討論請參閱 [欄位定義指南](../guide/column-defs)。 + +> 注意:json 資料中的「鍵」通常可以是任何內容,但鍵中的句點會被解讀為深層鍵,可能導致錯誤。 + +#### 巢狀子資料列 + +若使用展開功能,資料中常有巢狀子資料列,這會產生稍有不同的遞迴類型。 + +若資料如下: + +```json +[ + { + "firstName": "Tanner", + "lastName": "Linsley", + "subRows": [ + { + "firstName": "Kevin", + "lastName": "Vandy", + }, + { + "firstName": "John", + "lastName": "Doe", + "subRows": [ + //... + ] + } + ] + }, + { + "firstName": "Jane", + "lastName": "Doe", + } +] +``` + +您可以定義這樣的類型: + +```ts +type User = { + firstName: string + lastName: string + subRows?: User[] //不必命名為 "subRows",可任意命名 +} +``` + +其中 `subRows` 是 `User` 物件的可選陣列。更詳細的討論請參閱 [展開指南](../guide/expanding)。 + +### 給予資料「穩定」參照 + +傳遞給表格實例的 `data` 陣列 ***必須*** 有「穩定」的參照,以避免導致無限重新渲染的錯誤(特別是在 React 中)。 + +這取決於您使用的框架適配器,但在 React 中,通常應使用 `React.useState`、`React.useMemo` 或類似方法,確保 `data` 和 `columns` 表格選項有穩定的參照。 + +```tsx +const fallbackData = [] + +export default function MyComponent() { + //✅ 良好:`columns` 有穩定參照,不會導致無限重新渲染 + const columns = useMemo(() => [ + // ... + ], []); + + //✅ 良好:`data` 有穩定參照,不會導致無限重新渲染 + const [data, setData] = useState(() => [ + // ... + ]); + + // 欄位與資料定義於穩定參照中,不會導致無限迴圈! + const table = useReactTable({ + columns, + data ?? fallbackData, //也可使用定義於元件外的備用陣列(穩定參照) + }); + + return
+``` + +不過,如[進階欄位調整效能章節](#advanced-column-resizing-performance)所述,您可能需要考慮使用 CSS 變數來將欄位尺寸應用到您的標記語言。 + +##### 欄位調整 API + +TanStack Table 提供預建的事件處理器,讓您的拖曳互動更容易實作。這些事件處理器只是便利函數,會呼叫其他內部 API 來更新欄位尺寸狀態並重新渲染表格。使用 `header.getResizeHandler()` 來連接您的欄位調整拖曳互動,適用於滑鼠和觸控事件。 + +```tsx + +``` + +##### 使用 ColumnSizingInfoState 的欄位調整指示器 + +TanStack Table 會追蹤一個名為 `columnSizingInfo` 的狀態物件,您可以用它來渲染欄位調整指示器 UI。 + +```jsx + +``` + +#### 進階欄位調整效能 + +如果您正在建立大型或複雜的表格(並且使用 React 😉),您可能會發現如果沒有在渲染邏輯中加入適當的記憶化 (memoization),使用者在調整欄位時可能會遇到效能下降的問題。 + +我們建立了一個[高效能欄位調整範例](../framework/react/examples/column-resizing-performant),展示了如何在可能渲染緩慢的複雜表格中實現 60 fps 的欄位調整渲染。建議您直接查看該範例以了解如何實現,但以下是基本要點: + +1. 不要在每個標頭和每個資料單元格上使用 `column.getSize()`。相反,**記憶化**所有欄位寬度的計算結果! +2. 在調整過程中記憶化您的表格主體 (Table Body)。 +3. 使用 CSS 變數將欄位寬度傳遞給表格單元格。 + +如果遵循這些步驟,您應該能在調整欄位時看到顯著的效能提升。 + +如果您沒有使用 React,而是使用 Svelte、Vue 或 Solid 轉接器,可能不需要太擔心這些問題,但類似的原則仍然適用。 diff --git a/docs/zh-hant/guide/column-visibility.md b/docs/zh-hant/guide/column-visibility.md new file mode 100644 index 0000000000..0f3d788463 --- /dev/null +++ b/docs/zh-hant/guide/column-visibility.md @@ -0,0 +1,132 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:47.057Z' +title: 欄位可見性 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [column-visibility](../framework/react/examples/column-visibility) +- [column-ordering](../framework/react/examples/column-ordering) +- [sticky-column-pinning](../framework/react/examples/column-pinning-sticky) + +### 其他範例 + +- [SolidJS column-visibility](../framework/solid/examples/column-visibility) +- [Svelte column-visibility](../framework/svelte/examples/column-visibility) + +## API + +[Column Visibility API](../api/features/column-visibility) + +## 欄位可見性指南 + +欄位可見性功能允許動態隱藏或顯示表格欄位。在舊版 react-table 中,此功能是欄位的靜態屬性,但在 v8 版本中,提供了專用的 `columnVisibility` 狀態和 API 來動態管理欄位可見性。 + +### 欄位可見性狀態 + +`columnVisibility` 狀態是一個將欄位 ID 映射到布林值的物件。若欄位 ID 存在於該物件中且值為 `false`,該欄位將被隱藏。若欄位 ID 不存在於物件中,或值為 `true`,則欄位會顯示。 + +```jsx +const [columnVisibility, setColumnVisibility] = useState({ + columnId1: true, + columnId2: false, //預設隱藏此欄位 + columnId3: true, +}); + +const table = useReactTable({ + //... + state: { + columnVisibility, + //... + }, + onColumnVisibilityChange: setColumnVisibility, +}); +``` + +或者,若不需要在表格外部管理欄位可見性狀態,仍可使用 `initialState` 選項設定初始的預設欄位可見性狀態。 + +> **注意**:若 `columnVisibility` 同時提供給 `initialState` 和 `state`,`state` 的初始化將優先,`initialState` 會被忽略。請勿同時將 `columnVisibility` 提供給 `initialState` 和 `state`,只能選擇其中一種方式。 + +```jsx +const table = useReactTable({ + //... + initialState: { + columnVisibility: { + columnId1: true, + columnId2: false, //預設隱藏此欄位 + columnId3: true, + }, + //... + }, +}); +``` + +### 禁用欄位隱藏 + +預設情況下,所有欄位都可以被隱藏或顯示。若想防止特定欄位被隱藏,可將這些欄位的 `enableHiding` 選項設為 `false`。 + +```jsx +const columns = [ + { + header: 'ID', + accessorKey: 'id', + enableHiding: false, // 禁用此欄位的隱藏功能 + }, + { + header: 'Name', + accessor: 'name', // 可被隱藏 + }, +]; +``` + +### 欄位可見性切換 API + +有幾個欄位 API 方法可用於在使用者介面中渲染欄位可見性切換控制項: + +- `column.getCanHide` - 適用於禁用 `enableHiding` 設為 `false` 之欄位的可見性切換。 +- `column.getIsVisible` - 適用於設定可見性切換的初始狀態。 +- `column.toggleVisibility` - 適用於切換欄位的可見性。 +- `column.getToggleVisibilityHandler` - 將 `column.toggleVisibility` 方法連結到 UI 事件處理程序的快捷方式。 + +```jsx +{table.getAllColumns().map((column) => ( + +))} +``` + +### 欄位可見性感知的表格 API + +在渲染表頭、表身和表尾儲存格時,有許多 API 選項可用。你可能會看到像 `table.getAllLeafColumns` 和 `row.getAllCells` 這樣的 API,但若使用這些 API,它們不會考慮欄位可見性。此時,你需要使用這些 API 的「可見」變體,例如 `table.getVisibleLeafColumns` 和 `row.getVisibleCells`。 + +```jsx + + + + {table.getVisibleLeafColumns().map((column) => ( // 考慮欄位可見性 + // + ))} + + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( // 考慮欄位可見性 + // + ))} + + ))} + +
+``` + +若使用表頭群組 API,它們已自動考慮欄位可見性。 diff --git a/docs/zh-hant/guide/columns.md b/docs/zh-hant/guide/columns.md new file mode 100644 index 0000000000..6f9fe3de4f --- /dev/null +++ b/docs/zh-hant/guide/columns.md @@ -0,0 +1,73 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:16.794Z' +title: 欄位 +--- +## API + +[欄位 API](../api/core/column) + +## 欄位指南 + +> 注意:本指南討論的是表格實例中實際生成的 `column` 物件,而非設定表格的 [欄位定義](../guide/column-defs)。 + +本快速指南將討論在 TanStack Table 中獲取及操作 `column` 物件的各種方式。 + +### 獲取欄位的來源 + +`column` 物件可在多處取得,它們通常附屬於: + +#### 表頭與儲存格物件 + +在調用 `table` 實例 API 前,請先考慮是否需要取得 [表頭](../guide/headers) 或 [儲存格](../guide/cells) 而非直接取得 `columns`。若需渲染表格標記,通常應使用返回表頭或儲存格的 API 而非欄位物件。欄位物件本身並非直接用於渲染表頭或儲存格,但 `header` 和 `cell` 物件會包含這些 `column` 物件的參照,從而衍生出渲染 UI 所需的資訊。 + +```js +const column = cell.column; // 從儲存格取得欄位 +const column = header.column; // 從表頭取得欄位 +``` + +#### 欄位表格實例 API + +表格實例提供數十種 API 用於取得欄位,具體使用哪些 API 取決於表格功能與使用情境。 + +##### 取得單一欄位 + +若需透過 ID 取得單一欄位,可使用 `table.getColumn` API。 + +```js +const column = table.getColumn('firstName'); +``` + +##### 取得多個欄位 + +最基礎的欄位 API 是 `table.getAllColumns`,它會返回表格中所有欄位的列表。但此 API 搭配其他功能與表格狀態時,還有數十種衍生 API 可用,例如:`table.getAllFlatColumns`、`table.getAllLeafColumns`、`getCenterLeafColumns`、`table.getLeftVisibleLeafColumns` 等,這些 API 常與欄位可見性或固定欄位功能搭配使用。 + +### 欄位物件 + +欄位物件並非直接用於渲染表格 UI,因此不會與表格中的 `
` 或 `` 元素一一對應,但它們包含許多實用屬性和方法,可用於操作表格狀態。 + +#### 欄位 ID + +每個欄位在對應的 [欄位定義](../guide/column-defs) 中都必須有唯一的 `id`。通常需自行定義此 `id`,或由欄位定義中的 `accessorKey` 或 `header` 屬性衍生而來。 + +#### ColumnDef + +欄位物件始終保留原始 `columnDef` 物件的參照,該物件用於建立此欄位。 + +#### 巢狀群組欄位屬性 + +若欄位屬於巢狀或群組結構,以下屬性將特別有用: + +- `columns`:屬於群組欄位的子欄位陣列。 +- `depth`:欄位群組所屬的表頭群組「列索引」。 +- `parent`:欄位的父欄位。若為頂層欄位,此值為 `undefined`。 + +### 更多欄位 API + +數十種欄位 API 可用於操作表格狀態,並根據表格狀態提取儲存格值。詳情請參閱各功能的欄位 API 文件。 + +### 欄位渲染 + +不應直接使用 `column` 物件渲染 `headers` 或 `cells`,而應使用上述的 [`header`](../guide/headers) 和 [`cell`](../guide/cells) 物件。 + +但若需在 UI 其他地方渲染欄位列表(例如欄位可見性選單),可直接遍歷欄位陣列並照常渲染 UI。 diff --git a/docs/zh-hant/guide/custom-features.md b/docs/zh-hant/guide/custom-features.md new file mode 100644 index 0000000000..d196a857ca --- /dev/null +++ b/docs/zh-hant/guide/custom-features.md @@ -0,0 +1,286 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:43:01.997Z' +title: 自訂功能 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [custom-features](../framework/react/examples/custom-features) + +## 自訂功能指南 + +在本指南中,我們將介紹如何擴展 TanStack Table 的自訂功能,並在此過程中深入了解 TanStack Table v8 程式碼庫的結構與運作方式。 + +### TanStack Table 追求精簡 + +TanStack Table 內建一組核心功能,如排序、篩選、分頁等。我們收到許多功能請求,有時甚至是經過深思熟慮的 PR,希望為函式庫添加更多功能。雖然我們始終樂於改進函式庫,但也希望確保 TanStack Table 保持精簡,不會包含太多可能不會在大多數使用情境中用到的程式碼。並非每個 PR 都能或應該被納入核心函式庫,即使它確實解決了實際問題。這可能會讓開發者感到沮喪,尤其是當 TanStack Table 滿足他們 90% 的需求,但他們需要更多控制權時。 + +TanStack Table 的設計一直以來都允許高度擴展性(至少從 v7 開始)。無論你使用哪種框架適配器(`useReactTable`、`useVueTable` 等),返回的 `table` 實例都是一個普通的 JavaScript 物件,可以添加額外屬性或 API。一直以來,都可以使用組合(composition)來為表格實例添加自訂邏輯、狀態和 API。像 [Material React Table](https://github.com/KevinVandy/material-react-table/blob/v2/packages/material-react-table/src/hooks/useMRT_TableInstance.ts) 這樣的函式庫,就是通過在 `useReactTable` 鉤子外層創建自訂包裝鉤子來擴展表格實例的功能。 + +然而,從版本 8.14.0 開始,TanStack Table 提供了一個新的 `_features` 表格選項,讓你能夠以與內建表格功能完全相同的方式,更緊密且乾淨地將自訂程式碼整合到表格實例中。 + +> TanStack Table v8.14.0 引入了新的 `_features` 選項,允許你為表格實例添加自訂功能。 + +通過這種更緊密的整合,你可以輕鬆為表格添加更複雜的自訂功能,甚至可能將它們打包並與社群分享。我們將觀察這一功能的發展。在未來的 v9 版本中,我們甚至可能通過讓所有功能變為可選來進一步減少 TanStack Table 的套件大小,但這仍在探索中。 + +### TanStack Table 功能的工作原理 + +TanStack Table 的原始碼可以說相當簡單(至少我們這麼認為)。每個功能的程式碼都被拆分到各自的物件/檔案中,包含創建初始狀態的方法、預設表格和欄位選項,以及可以添加到 `table`、`header`、`column`、`row` 和 `cell` 實例的 API 方法。 + +所有功能物件的功能都可以用從 TanStack Table 導出的 `TableFeature` 類型來描述。這是一個 TypeScript 介面,描述了創建功能所需的功能物件的結構。 + +```ts +export interface TableFeature { + createCell?: ( + cell: Cell, + column: Column, + row: Row, + table: Table + ) => void + createColumn?: (column: Column, table: Table) => void + createHeader?: (header: Header, table: Table) => void + createRow?: (row: Row, table: Table) => void + createTable?: (table: Table) => void + getDefaultColumnDef?: () => Partial> + getDefaultOptions?: ( + table: Table + ) => Partial> + getInitialState?: (initialState?: InitialTableState) => Partial +} +``` + +這可能有點令人困惑,因此讓我們分解這些方法的作用: + +#### 預設選項與初始狀態 + +
+ +##### getDefaultOptions + +表格功能中的 `getDefaultOptions` 方法負責為該功能設定預設的表格選項。例如,在 [欄位調整大小](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/ColumnSizing.ts) 功能中,`getDefaultOptions` 方法會設定預設的 `columnResizeMode` 選項,其預設值為 `"onEnd"`。 + +
+ +##### getDefaultColumnDef + +表格功能中的 `getDefaultColumnDef` 方法負責為該功能設定預設的欄位選項。例如,在 [排序](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/RowSorting.ts) 功能中,`getDefaultColumnDef` 方法會設定預設的 `sortUndefined` 欄位選項,其預設值為 `1`。 + +
+ +##### getInitialState + +表格功能中的 `getInitialState` 方法負責為該功能設定預設的狀態。例如,在 [分頁](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/RowPagination.ts) 功能中,`getInitialState` 方法會設定預設的 `pageSize` 狀態為 `10`,以及預設的 `pageIndex` 狀態為 `0`。 + +#### API 創建器 + +
+ +##### createTable + +表格功能中的 `createTable` 方法負責為 `table` 實例添加方法。例如,在 [列選擇](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/RowSelection.ts) 功能中,`createTable` 方法會添加許多表格實例 API 方法,如 `toggleAllRowsSelected`、`getIsAllRowsSelected`、`getIsSomeRowsSelected` 等。因此,當你調用 `table.toggleAllRowsSelected()` 時,你實際上是在調用由 `RowSelection` 功能添加到表格實例的方法。 + +
+ +##### createHeader + +表格功能中的 `createHeader` 方法負責為 `header` 實例添加方法。例如,在 [欄位調整大小](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/ColumnSizing.ts) 功能中,`createHeader` 方法會添加許多標頭實例 API 方法,如 `getStart` 等。因此,當你調用 `header.getStart()` 時,你實際上是在調用由 `ColumnSizing` 功能添加到標頭實例的方法。 + +
+ +##### createColumn + +表格功能中的 `createColumn` 方法負責為 `column` 實例添加方法。例如,在 [排序](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/RowSorting.ts) 功能中,`createColumn` 方法會添加許多欄位實例 API 方法,如 `getNextSortingOrder`、`toggleSorting` 等。因此,當你調用 `column.toggleSorting()` 時,你實際上是在調用由 `RowSorting` 功能添加到欄位實例的方法。 + +
+ +##### createRow + +表格功能中的 `createRow` 方法負責為 `row` 實例添加方法。例如,在 [列選擇](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/RowSelection.ts) 功能中,`createRow` 方法會添加許多列實例 API 方法,如 `toggleSelected`、`getIsSelected` 等。因此,當你調用 `row.toggleSelected()` 時,你實際上是在調用由 `RowSelection` 功能添加到列實例的方法。 + +
+ +##### createCell + +表格功能中的 `createCell` 方法負責為 `cell` 實例添加方法。例如,在 [欄位分組](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/ColumnGrouping.ts) 功能中,`createCell` 方法會添加許多儲存格實例 API 方法,如 `getIsGrouped`、`getIsAggregated` 等。因此,當你調用 `cell.getIsGrouped()` 時,你實際上是在調用由 `ColumnGrouping` 功能添加到儲存格實例的方法。 + +### 添加自訂功能 + +讓我們通過一個假設的使用案例來逐步創建一個自訂表格功能。假設我們想在表格實例中添加一個功能,允許使用者更改表格的「密度」(儲存格的內邊距)。 + +查看完整的 [custom-features](../framework/react/examples/custom-features) 範例以了解完整實現,以下是創建自訂功能的詳細步驟。 + +#### 步驟 1:設定 TypeScript 類型 + +假設你希望與 TanStack Table 內建功能具有相同的完整類型安全性,讓我們為新功能設定所有 TypeScript 類型。我們將為新的表格選項、狀態和表格實例 API 方法創建類型。 + +這些類型遵循 TanStack Table 內部使用的命名慣例,但你可以隨意命名。我們尚未將這些類型添加到 TanStack Table 中,但將在下一步進行。 + +```ts +// 為新功能的自訂狀態定義類型 +export type DensityState = 'sm' | 'md' | 'lg' +export interface DensityTableState { + density: DensityState +} + +// 為新功能的表格選項定義類型 +export interface DensityOptions { + enableDensity?: boolean + onDensityChange?: OnChangeFn +} + +// 為新功能的表格 API 定義類型 +export interface DensityInstance { + setDensity: (updater: Updater) => void + toggleDensity: (value?: DensityState) => void +} +``` + +#### 步驟 2:使用宣告合併將新類型添加到 TanStack Table + +我們可以告訴 TypeScript 修改從 TanStack Table 導出的類型,以包含我們新功能的類型。這稱為「宣告合併」(declaration merging),是 TypeScript 的一個強大功能。這樣,我們在新功能的程式碼或應用程式碼中就不需要使用任何 TypeScript 技巧,例如 `as unknown as CustomTable` 或 `// @ts-ignore`。 + +```ts +// 使用宣告合併將新功能的 API 和狀態類型添加到 TanStack Table 的現有類型中。 +declare module '@tanstack/react-table' { // 或你正在使用的任何框架適配器 + // 將新功能的狀態與現有表格狀態合併 + interface TableState extends DensityTableState {} + // 將新功能的選項與現有表格選項合併 + interface TableOptionsResolved + extends DensityOptions {} + // 將新功能的實例 API 與現有表格實例 API 合併 + interface Table extends DensityInstance {} + // 如果需要添加儲存格實例 API... + // interface Cell extends DensityCell + // 如果需要添加列實例 API... + // interface Row extends DensityRow + // 如果需要添加欄位實例 API... + // interface Column extends DensityColumn + // 如果需要添加標頭實例 API... + // interface Header extends DensityHeader + + // 注意:無法對 `ColumnDef` 進行宣告合併,因為它是一個複雜類型,而非介面。 + // 但你仍然可以對 `ColumnDef.meta` 進行宣告合併。 +} +``` + +一旦正確完成此操作,我們在嘗試創建新功能的程式碼並在應用程式中使用它時,應該不會有任何 TypeScript 錯誤。 + +##### 使用宣告合併的注意事項 + +使用宣告合併的一個注意事項是,它會影響程式碼庫中所有表格的 TanStack Table 類型。如果你計劃為應用程式中的每個表格加載相同的功能集,這不是問題,但如果某些表格加載額外功能而某些不加載,則可能會出現問題。或者,你可以創建一堆自訂類型,從 TanStack Table 類型擴展並添加新功能。[Material React Table](https://github.com/KevinVandy/material-react-table/blob/v2/packages/material-react-table/src/types.ts) 就是這樣做的,以避免影響原生 TanStack Table 表格的類型,但這會更繁瑣,並且在某些地方需要大量類型轉換。 + +#### 步驟 3:創建功能物件 + +完成所有 TypeScript 設定後,我們現在可以為新功能創建功能物件。在這裡,我們定義將添加到表格實例的所有方法。 + +使用 `TableFeature` 類型確保你正確創建功能物件。如果 TypeScript 類型設定正確,你在創建帶有新狀態、選項和實例 API 的功能物件時,應該不會有任何 TypeScript 錯誤。 + +```ts +export const DensityFeature: TableFeature = { // 使用 TableFeature 類型!! + // 定義新功能的初始狀態 + getInitialState: (state): DensityTableState => { + return { + density: 'md', + ...state, + } + }, + + // 定義新功能的預設選項 + getDefaultOptions: ( + table: Table + ): DensityOptions => { + return { + enableDensity: true, + onDensityChange: makeStateUpdater('density', table), + } as DensityOptions + }, + // 如果需要添加預設欄位定義... + // getDefaultColumnDef: (): Partial> => { + // return { meta: {} } // 使用 meta 而非直接添加到 columnDef,以避免難以解決的 TypeScript 問題 + // }, + + // 定義新功能的表格實例方法 + createTable: (table: Table): void => { + table.setDensity = updater => { + const safeUpdater: Updater = old => { + let newState = functionalUpdate(updater, old) + return newState + } + return table.options.onDensityChange?.(safeUpdater) + } + table.toggleDensity = value => { + table.setDensity(old => { + if (value) return value + return old === 'lg' ? 'md' : old === 'md' ? 'sm' : 'lg' // 在三種選項之間循環 + }) + } + }, + + // 如果需要添加列實例 API... + // createRow: (row, table): void => {}, + // 如果需要添加儲存格實例 API... + // createCell: (cell, column, row, table): void => {}, + // 如果需要添加欄位實例 API... + // createColumn: (column, table): void => {}, + // 如果需要添加標頭實例 API... + // createHeader: (header, table): void => {}, +} +``` + +#### 步驟 4:將功能添加到表格 + +現在我們有了功能物件,可以在創建表格實例時將其傳遞給 `_features` 選項,從而將其添加到表格實例中。 + +```ts +const table = useReactTable({ + _features: [DensityFeature], // 將新功能傳遞給表格,以在底層與所有內建功能合併 + columns, + data, + //.. +}) +``` + +#### 步驟 5:在應用程式中使用功能 + +現在功能已添加到表格實例中,你可以在應用程式中使用新的實例 API、選項和狀態。 + +```tsx +const table = useReactTable({ + _features: [DensityFeature], // 將自訂功能傳遞給表格以在創建時實例化 + columns, + data, + //... + state: { + density, // 將密度狀態傳遞給表格,TypeScript 仍然正常 :) + }, + onDensityChange: setDensity, // 使用新的 onDensityChange 選項,TypeScript 仍然正常 :) +}) +//... +const { density } = table.getState() +return( +
+ {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} +
...
; +} +``` + +`React.useState` 和 `React.useMemo` 並非唯一提供穩定參照的方法。您也可將資料定義於元件外,或使用第三方狀態管理函式庫如 Redux、Zustand 或 TanStack Query。 + +主要需避免的是在與 `useReactTable` 呼叫相同的範圍內定義 `data` 陣列。這會導致 `data` 陣列在每次渲染時重新定義,進而引發無限重新渲染的迴圈。 + +```tsx +export default function MyComponent() { + //😵 不良:`columns` 在每次渲染時重新定義為新陣列,會導致無限重新渲染! + const columns = [ + // ... + ]; + + //😵 不良:`data` 在每次渲染時重新定義為新陣列,會導致無限重新渲染! + const data = [ + // ... + ]; + + //❌ 欄位與資料定義於 `useReactTable` 相同範圍且無穩定參照,會導致無限迴圈! + const table = useReactTable({ + columns, + data ?? [], //❌ 備用陣列在每次渲染時重新建立,同樣不良 + }); + + return ...
; +} +``` + +### TanStack Table 如何轉換資料 + +在文件的其他部分,您將看到 TanStack Table 如何處理傳遞給表格的 `data`,並產生用於建立表格的資料列與儲存格物件。TanStack Table 不會變更您傳遞的 `data`,但資料列與儲存格中的實際值可能透過欄位定義中的存取器,或由 [資料列模型](../guide/row-models) 執行的其他功能(如分組或聚合)轉換。 + +### TanStack Table 能處理多少資料? + +信不信由您,TanStack Table 實際上設計用於在客戶端處理可能高達數十萬筆的資料列。當然,這取決於每欄資料的大小與欄位數量,並非總是可行。然而,排序、篩選、分頁與分組功能皆以高效能處理大型資料集為設計考量。 + +開發者建立資料表格時,通常預設對大型資料集實作伺服器端分頁、排序與篩選。這通常仍是好主意,但許多開發者低估了現代瀏覽器與適當優化下,客戶端實際能處理的資料量。若表格永遠不會超過數千筆資料列,您或許能利用 TanStack Table 的客戶端功能,而非自行在伺服器實作。當然,在讓 TanStack Table 的客戶端功能處理大型資料集前,應以實際資料測試其效能是否符合需求。 + +更詳細的討論請參閱 [分頁指南](../guide/pagination#should-you-use-client-side-pagination)。 diff --git a/docs/zh-hant/guide/expanding.md b/docs/zh-hant/guide/expanding.md new file mode 100644 index 0000000000..7ccf766997 --- /dev/null +++ b/docs/zh-hant/guide/expanding.md @@ -0,0 +1,230 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:52.079Z' +title: 展開 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [展開功能](../framework/react/examples/expanding) +- [分組功能](../framework/react/examples/grouping) +- [子元件](../framework/react/examples/sub-components) + +## API + +[展開功能 API](../api/features/expanding) + +## 展開功能指南 + +展開功能允許你顯示或隱藏與特定資料列相關的額外資料列。這在以下情境特別有用:當你擁有階層式資料時,可以讓使用者從上層資料向下鑽研;或是當你需要顯示與某列相關的額外資訊時。 + +### 展開功能的不同應用場景 + +TanStack Table 的展開功能有以下幾種常見應用場景: + +1. 展開子列(子資料列、彙總列等) +2. 展開自訂 UI(詳細面板、子表格等) + +### 啟用客戶端展開功能 + +要使用客戶端展開功能,你需要在表格選項中定義 `getExpandedRowModel` 函式。這個函式負責回傳展開後的資料列模型。 + +```ts +const table = useReactTable({ + // 其他選項... + getExpandedRowModel: getExpandedRowModel(), +}) +``` + +展開的資料可以包含表格列或任何你想顯示的資料。本指南將討論如何處理這兩種情況。 + +### 將表格列作為展開資料 + +展開列本質上是繼承父列相同欄位結構的子列。如果你的資料物件已包含這些展開列資料,可以使用 `getSubRows` 函式來指定這些子列。如果資料物件不包含展開列資料,則可將其視為自訂展開資料(將在下一節討論)。 + +例如,如果你有以下資料物件: + +```ts +type Person = { + id: number + name: string + age: number + children?: Person[] | undefined +} + +const data: Person[] = [ + { id: 1, + name: 'John', + age: 30, + children: [ + { id: 2, name: 'Jane', age: 5 }, + { id: 5, name: 'Jim', age: 10 } + ] + }, + { id: 3, + name: 'Doe', + age: 40, + children: [ + { id: 4, name: 'Alice', age: 10 } + ] + }, +] +``` + +你可以使用 `getSubRows` 函式將每列的 `children` 陣列作為展開列回傳。表格實例現在會知道在每列中哪裡可以找到子列。 + +```ts +const table = useReactTable({ + // 其他選項... + getSubRows: (row) => row.children, // 將 children 陣列作為子列回傳 + getCoreRowModel: getCoreRowModel(), + getExpandedRowModel: getExpandedRowModel(), +}) +``` + +> **注意:** 你可以使用複雜的 `getSubRows` 函式,但請注意它會對每列和每個子列執行。如果函式未優化,可能會影響效能。不支援非同步函式。 + +### 自訂展開 UI + +在某些情況下,你可能希望顯示額外細節或資訊(這些資訊可能是或不是表格資料物件的一部分),例如列的展開資料。這類展開列 UI 多年來有許多名稱,包括「可展開列」、「詳細面板」、「子元件」等。 + +預設情況下,`row.getCanExpand()` 列實例 API 會回傳 false,除非它在列上找到 `subRows`。你可以透過在表格實例選項中實作自己的 `getRowCanExpand` 函式來覆寫此行為。 + +```ts +//... +const table = useReactTable({ + // 其他選項... + getRowCanExpand: (row) => true, // 新增你的邏輯來決定列是否可以展開。true 表示所有列都包含展開資料 + getCoreRowModel: getCoreRowModel(), + getExpandedRowModel: getExpandedRowModel(), +}) +//... + + {table.getRowModel().rows.map((row) => ( + + {/* 正常列 UI */} + + {row.getVisibleCells().map((cell) => ( + + + + ))} + + {/* 如果列已展開,將展開的 UI 渲染為一個單獨的列,其單一儲存格橫跨表格的寬度 */} + {row.getIsExpanded() && ( + + // 如果展開資料不是與父列共享相同欄位的列,則指定要橫跨的欄位數 + // 你的自訂 UI 放在這裡 + + + )} + + ))} + +//... +``` + +### 展開列狀態 + +如果需要控制表格中列的展開狀態,可以使用 `expanded` 狀態和 `onExpandedChange` 選項來實現。這允許你根據需求管理展開狀態。 + +```ts +const [expanded, setExpanded] = useState({}) + +const table = useReactTable({ + // 其他選項... + state: { + expanded: expanded, // 必須將展開狀態傳回表格 + }, + onExpandedChange: setExpanded +}) +``` + +`ExpandedState` 類型定義如下: + +```ts +type ExpandedState = true | Record +``` + +如果 `ExpandedState` 為 true,表示所有列都已展開。如果是記錄(record),則只有 ID 作為鍵且值設為 true 的列會被展開。例如,如果展開狀態為 `{ row1: true, row2: false }`,表示 ID 為 row1 的列已展開,而 row2 的列未展開。表格使用此狀態來決定哪些列應展開並顯示其子列(如果有的話)。 + +### 展開列的 UI 切換處理器 + +TanStack Table 不會為你的表格新增展開資料的切換處理器 UI。你應該手動在每列的 UI 中新增它,以允許使用者展開和摺疊列。例如,你可以在欄位定義中新增按鈕 UI。 + +```ts +const columns = [ + { + accessorKey: 'name', + header: 'Name', + }, + { + accessorKey: 'age', + header: 'Age', + }, + { + header: 'Children', + cell: ({ row }) => { + return row.getCanExpand() ? + + : ''; + }, + }, +] +``` + +### 篩選展開列 + +預設情況下,篩選過程從父列開始並向下移動。這意味著如果父列被篩選排除,其所有子列也會被排除。但是,你可以透過使用 `filterFromLeafRows` 選項來改變此行為。啟用此選項後,篩選過程從葉(子)列開始並向上移動。這確保只要至少一個子列或孫列符合篩選條件,父列就會包含在篩選結果中。此外,你可以使用 `maxLeafRowFilterDepth` 選項控制篩選過程深入子階層的程度。此選項允許你指定篩選應考慮的子列最大深度。 + +```ts +//... +const table = useReactTable({ + // 其他選項... + getSubRows: row => row.subRows, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getExpandedRowModel: getExpandedRowModel(), + filterFromLeafRows: true, // 搜尋展開列 + maxLeafRowFilterDepth: 1, // 限制搜尋的展開列深度 +}) +``` + +### 分頁展開列 + +預設情況下,展開列會與表格的其他部分一起分頁(這意味著展開列可能會跨越多個頁面)。如果你想禁用此行為(這意味著展開列將始終在其父列的頁面上渲染。這也表示會渲染比設定的頁面大小更多的列),可以使用 `paginateExpandedRows` 選項。 + +```ts +const table = useReactTable({ + // 其他選項... + paginateExpandedRows: false, +}) +``` + +### 固定展開列 + +固定展開列的方式與固定普通列相同。你可以將展開列固定在表格的頂部或底部。有關列固定的更多資訊,請參閱[固定指南](./pinning.md)。 + +### 排序展開列 + +預設情況下,展開列會與表格的其他部分一起排序。 + +### 手動展開(伺服器端) + +如果你正在進行伺服器端展開,可以透過將 `manualExpanding` 選項設為 true 來啟用手動列展開。這意味著 `getExpandedRowModel` 不會用於展開列,你需要在自己的資料模型中執行展開操作。 + +```ts +const table = useReactTable({ + // 其他選項... + manualExpanding: true, +}) +``` diff --git a/docs/zh-hant/guide/features.md b/docs/zh-hant/guide/features.md new file mode 100644 index 0000000000..f18f5fcf83 --- /dev/null +++ b/docs/zh-hant/guide/features.md @@ -0,0 +1,24 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:41.379Z' +title: Features Guide +--- +# 功能指南 (Features Guide) + +TanStack Table 提供多種功能,每項功能都有其對應的選項和 API: + +- [欄位排序 (Column Ordering)](../guide/column-ordering) +- [欄位固定 (Column Pinning)](../guide/column-pinning) +- [欄位尺寸調整 (Column Sizing)](../guide/column-sizing) +- [欄位可見性 (Column Visibility)](../guide/column-visibility) +- [展開功能 (Expanding)](../guide/expanding) +- [欄位分面 (Column Faceting)](../guide/column-faceting) +- [欄位過濾 (Column Filtering)](../guide/column-filtering) +- [全域分面 (Global Faceting)](../guide/global-faceting) +- [全域過濾 (Global Filtering)](../guide/global-filtering) +- [分組功能 (Grouping)](../guide/grouping) +- [分頁功能 (Pagination)](../guide/pagination) +- [行固定 (Row Pinning)](../guide/row-pinning) +- [行選取 (Row Selection)](../guide/row-selection) +- [排序功能 (Sorting)](../guide/sorting) +- [虛擬化 (Virtualization)](../guide/virtualization) diff --git a/docs/zh-hant/guide/filters.md b/docs/zh-hant/guide/filters.md new file mode 100644 index 0000000000..492d6fc5ed --- /dev/null +++ b/docs/zh-hant/guide/filters.md @@ -0,0 +1,14 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:35.388Z' +title: Filters Guide +--- + + +篩選器指南現已拆分為多個獨立指南: + +- [欄位篩選 (Column Filtering)](../guide/column-filtering) +- [全域篩選 (Global Filtering)](../guide/global-filtering) +- [模糊篩選 (Fuzzy Filtering)](../guide/fuzzy-filtering) +- [欄位面向 (Column Faceting)](../guide/column-faceting) +- [全域面向 (Global Faceting)](../guide/global-faceting) diff --git a/docs/zh-hant/guide/fuzzy-filtering.md b/docs/zh-hant/guide/fuzzy-filtering.md new file mode 100644 index 0000000000..3a73863940 --- /dev/null +++ b/docs/zh-hant/guide/fuzzy-filtering.md @@ -0,0 +1,125 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:09.670Z' +title: 模糊過濾 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [filters-fuzzy](../framework/react/examples/filters-fuzzy) + +## API + +[篩選器 API](../api/features/filters) + +## 模糊篩選指南 + +模糊篩選 (Fuzzy Filtering) 是一種基於近似匹配來過濾資料的技術。當您需要搜尋與給定值相似而非完全匹配的資料時,這項技術特別有用。 + +您可以透過定義自訂篩選函式來實作客戶端模糊篩選。此函式應接收 row、columnId 和 filter value 作為參數,並回傳一個布林值來決定該列是否應包含在篩選結果中。 + +模糊篩選最常與全域篩選 (global filtering) 搭配使用,但也能應用於個別欄位。我們將討論如何在這兩種情況下實作模糊篩選。 + +> **注意:** 使用模糊篩選需先安裝 `@tanstack/match-sorter-utils` 函式庫。 +> TanStack Match Sorter Utils 是 [match-sorter](https://github.com/kentcdodds/match-sorter) 的分支版本,由 Kent C. Dodds 開發。此分支版本是為了更好地配合 TanStack Table 的逐列篩選 (row by row filtering) 方式。 + +使用 match-sorter 函式庫是可選的,但 TanStack Match Sorter Utils 函式庫提供了絕佳的方式來進行模糊篩選,並根據回傳的排序資訊 (rank information) 進行排序,讓資料列能依照與搜尋條件的匹配程度排序。 + +### 定義自訂模糊篩選函式 + +以下是自訂模糊篩選函式的範例: + +```typescript +import { rankItem } from '@tanstack/match-sorter-utils'; +import { FilterFn } from '@tanstack/table'; + +const fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => { + // 對項目進行評分 + const itemRank = rankItem(row.getValue(columnId), value) + + // 儲存 itemRank 資訊 + addMeta({ itemRank }) + + // 回傳該項目是否應被保留在篩選結果中 + return itemRank.passed +} +``` + +在此函式中,我們使用 @tanstack/match-sorter-utils 函式庫的 rankItem 函式來評分項目。接著將評分資訊儲存在該列的 meta 資料中,並回傳該項目是否符合評分標準。 + +### 搭配全域篩選使用模糊篩選 + +要搭配全域篩選使用模糊篩選,您可以在表格實例的 globalFilterFn 選項中指定模糊篩選函式: + +```typescript +const table = useReactTable({ // 或您使用框架的等效函式 + columns, + data, + filterFns: { + fuzzy: fuzzyFilter, //定義為可在欄位定義中使用的篩選函式 + }, + globalFilterFn: 'fuzzy', //將模糊篩選應用於全域篩選(模糊篩選最常見的使用情境) + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), //客戶端篩選 + getSortedRowModel: getSortedRowModel(), //如需排序功能也需啟用客戶端排序 +}) +``` + +### 搭配欄位篩選使用模糊篩選 + +要搭配欄位篩選使用模糊篩選,您應先在表格實例的 filterFns 選項中定義模糊篩選函式。接著在欄位定義的 filterFn 選項中指定該函式: + +```typescript +const column = [ + { + accessorFn: row => `${row.firstName} ${row.lastName}`, + id: 'fullName', + header: 'Full Name', + cell: info => info.getValue(), + filterFn: 'fuzzy', //使用我們的自訂模糊篩選函式 + }, + // 其他欄位... +]; +``` + +在此範例中,我們將模糊篩選應用於組合了資料中 firstName 和 lastName 欄位的全名欄位。 + +#### 搭配模糊篩選進行排序 + +當搭配欄位篩選使用模糊篩選時,您可能還想根據評分資訊排序資料。您可以透過定義自訂排序函式來實現: + +```typescript +import { compareItems } from '@tanstack/match-sorter-utils' +import { sortingFns } from '@tanstack/table' + +const fuzzySort: SortingFn = (rowA, rowB, columnId) => { + let dir = 0 + + // 僅在欄位有評分資訊時才進行排序 + if (rowA.columnFiltersMeta[columnId]) { + dir = compareItems( + rowA.columnFiltersMeta[columnId]?.itemRank!, + rowB.columnFiltersMeta[columnId]?.itemRank! + ) + } + + // 當項目評分相同時,改用字母數字排序作為備援方案 + return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir +} +``` + +在此函式中,我們比較兩列資料的評分資訊。若評分相同,則改用字母數字排序 (alphanumeric sorting)。 + +接著您可以在欄位定義的 sortFn 選項中指定此排序函式: + +```typescript +{ + accessorFn: row => `${row.firstName} ${row.lastName}`, + id: 'fullName', + header: 'Full Name', + cell: info => info.getValue(), + filterFn: 'fuzzy', //使用我們的自訂模糊篩選函式 + sortFn: 'fuzzySort', //使用我們的自訂模糊排序函式 +} +``` diff --git a/docs/zh-hant/guide/global-faceting.md b/docs/zh-hant/guide/global-faceting.md new file mode 100644 index 0000000000..8e72bc875b --- /dev/null +++ b/docs/zh-hant/guide/global-faceting.md @@ -0,0 +1,80 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:43.880Z' +title: 全域面向 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [filters-faceted](../framework/react/examples/filters) + +## API + +[全域分面 API](../api/features/global-faceting) + +## 全域分面指南 (Global Faceting) + +全域分面功能可讓您從表格資料中為所有欄位生成值列表。例如,可以從所有欄位的所有列中生成唯一值列表,作為自動完成篩選元件的搜尋建議。或者,可以從數字表格中生成最小值和最大值的元組,作為範圍滑桿篩選元件的範圍。 + +### 全域分面行模型 (Global Faceting Row Models) + +若要使用任何全域分面功能,您必須在表格選項中包含適當的行模型。 + +```ts +//僅導入您需要的行模型 +import { + getCoreRowModel, + getFacetedRowModel, + getFacetedMinMaxValues, //依賴於 getFacetedRowModel + getFacetedUniqueValues, //依賴於 getFacetedRowModel +} from '@tanstack/react-table' +//... +const table = useReactTable({ + // 其他選項... + getCoreRowModel: getCoreRowModel(), + getFacetedRowModel: getFacetedRowModel(), //用於客戶端分面的分面模型 (其他分面方法依賴此模型) + getFacetedMinMaxValues: getFacetedMinMaxValues(), //如果您需要最小/最大值 + getFacetedUniqueValues: getFacetedUniqueValues(), //如果您需要唯一值列表 + //... +}) +``` + +### 使用全域分面行模型 + +在表格選項中包含適當的行模型後,您將能夠使用分面表格實例 API 來存取由分面行模型生成的值列表。 + +```ts +// 用於自動完成篩選的唯一值列表 +const autoCompleteSuggestions = + Array.from(table.getGlobalFacetedUniqueValues().keys()) + .sort() + .slice(0, 5000); +``` + +```ts +// 用於範圍篩選的最小和最大值元組 +const [min, max] = table.getGlobalFacetedMinMaxValues() ?? [0, 1]; +``` + +### 自訂全域 (伺服器端) 分面 + +如果不使用內建的客戶端分面功能,您可以在伺服器端實作自己的分面邏輯,並將分面值傳遞到客戶端。您可以使用 getGlobalFacetedUniqueValues 和 getGlobalFacetedMinMaxValues 表格選項來解析來自伺服器端的分面值。 + +```ts +const facetingQuery = useQuery( + 'faceting', + async () => { + const response = await fetch('/api/faceting'); + return response.json(); + }, + { + onSuccess: (data) => { + table.getGlobalFacetedUniqueValues = () => data.uniqueValues; + table.getGlobalFacetedMinMaxValues = () => data.minMaxValues; + }, + } +); +``` + +在此範例中,我們使用來自 `react-query` 的 `useQuery` 鉤子 (hook) 從伺服器獲取分面資料。獲取資料後,我們設定 `getGlobalFacetedUniqueValues` 和 `getGlobalFacetedMinMaxValues` 表格選項以返回伺服器回應中的分面值。這將允許表格使用伺服器端分面資料來生成自動完成建議和範圍篩選器。 diff --git a/docs/zh-hant/guide/global-filtering.md b/docs/zh-hant/guide/global-filtering.md new file mode 100644 index 0000000000..f3cff0d5ec --- /dev/null +++ b/docs/zh-hant/guide/global-filtering.md @@ -0,0 +1,198 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:22.082Z' +title: 全域過濾 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [全域篩選](../framework/react/examples/filters-global) + +## API + +[全域篩選 API](../api/features/global-filtering) + +## 全域篩選指南 + +篩選功能分為兩種:欄位篩選 (Column Filtering) 與全域篩選 (Global Filtering)。 + +本指南將重點介紹全域篩選,這是套用至所有欄位的篩選方式。 + +### 客戶端篩選 vs 伺服器端篩選 + +若您有大型資料集,可能不希望將所有資料載入客戶端瀏覽器進行篩選。在這種情況下,您很可能需要實作伺服器端篩選、排序、分頁等功能。 + +然而,如 [分頁指南](../guide/pagination#should-you-use-client-side-pagination) 中所述,許多開發者低估了客戶端能處理的資料量而不影響效能。TanStack Table 的範例通常測試可處理高達 100,000 列或更多資料,並在客戶端篩選、排序、分頁和分組時保持良好效能。這不代表您的應用程式一定能處理這麼多資料列,但如果您的表格最多只有幾千列,或許可以利用 TanStack Table 提供的客戶端篩選、排序、分頁和分組功能。 + +> TanStack Table 能高效處理數千列的客戶端資料。在未經思考前,請勿直接排除客戶端篩選、分頁、排序等功能。 + +每個使用情境不同,取決於表格的複雜度、欄位數量、資料大小等因素。需注意的主要瓶頸包括: + +1. 您的伺服器能否在合理時間(和成本)內查詢所有資料? +2. 獲取的資料總大小為何?(若欄位不多,實際影響可能不如想像嚴重。) +3. 若一次性載入所有資料,客戶端瀏覽器是否會使用過多記憶體? + +若不確定,可以先從客戶端篩選和分頁開始,待資料增長後再切換至伺服器端策略。 + +### 手動伺服器端全域篩選 + +若您決定實作伺服器端全域篩選而非使用內建的客戶端全域篩選,以下是實作方式。 + +手動伺服器端全域篩選不需要 `getFilteredRowModel` 表格選項。相反地,傳遞給表格的 `data` 應已篩選完成。但若您已設定 `getFilteredRowModel` 選項,可透過將 `manualFiltering` 設為 `true` 來跳過此選項。 + +```jsx +const table = useReactTable({ + data, + columns, + // getFilteredRowModel: getFilteredRowModel(), // 手動伺服器端全域篩選不需要此選項 + manualFiltering: true, +}) +``` + +注意:使用手動全域篩選時,本指南後續討論的許多選項將無效。當 `manualFiltering` 設為 `true` 時,表格實例不會對傳入的資料列套用任何全域篩選邏輯,而是假設資料列已篩選完成並直接使用傳入的資料。 + +### 客戶端全域篩選 + +若使用內建的客戶端全域篩選,首先需在表格選項中傳入 `getFilteredRowModel` 函式。 + +```jsx +import { useReactTable, getFilteredRowModel } from '@tanstack/react-table' +//... +const table = useReactTable({ + // 其他選項... + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), // 客戶端全域篩選需要此選項 +}) +``` + +### 全域篩選函式 + +`globalFilterFn` 選項可讓您指定用於全域篩選的篩選函式。篩選函式可以是內建篩選函式的名稱字串、透過 `tableOptions.filterFns` 提供的自訂篩選函式名稱字串,或直接傳入自訂篩選函式。 + +```jsx +const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + globalFilterFn: 'text' // 內建篩選函式 +}) +``` + +預設提供 10 種內建篩選函式: + +- includesString - 不區分大小寫的字串包含 +- includesStringSensitive - 區分大小寫的字串包含 +- equalsString - 不區分大小寫的字串相等 +- equalsStringSensitive - 區分大小寫的字串相等 +- arrIncludes - 陣列項目包含 +- arrIncludesAll - 陣列包含所有項目 +- arrIncludesSome - 陣列包含部分項目 +- equals - 物件/參照相等 Object.is/=== +- weakEquals - 弱型別物件/參照相等 == +- inNumberRange - 數字範圍包含 + +您也可以直接定義自訂篩選函式並傳入 `globalFilterFn` 選項。 + +### 全域篩選狀態 + +全域篩選狀態儲存於表格的內部狀態中,可透過 `table.getState().globalFilter` 存取。若需在表格外部持久化全域篩選狀態,可使用 `onGlobalFilterChange` 選項提供回呼函式,在狀態變更時呼叫。 + +```jsx +const [globalFilter, setGlobalFilter] = useState([]) + +const table = useReactTable({ + // 其他選項... + state: { + globalFilter, + }, + onGlobalFilterChange: setGlobalFilter +}) +``` + +全域篩選狀態的結構如下: + +```jsx +interface GlobalFilter { + globalFilter: any +} +``` + +### 在 UI 中加入全域篩選輸入框 + +TanStack Table 不會自動加入全域篩選輸入框至您的表格。您需手動在 UI 中加入,讓使用者能篩選表格。例如,可在表格上方加入輸入框讓使用者輸入搜尋詞。 + +```jsx +return ( +
+ table.setGlobalFilter(String(e.target.value))} + placeholder="搜尋..." + /> +
+) +``` + +### 自訂全域篩選函式 + +若需使用自訂全域篩選函式,可定義函式並傳入 `globalFilterFn` 選項。 + +> **注意:** 常有人使用模糊篩選函式進行全域篩選。相關討論請見 [模糊篩選指南](./fuzzy-filtering.md)。 + +```jsx +const customFilterFn = (rows, columnId, filterValue) => { + // 自訂篩選邏輯 +} + +const table = useReactTable({ + // 其他選項... + globalFilterFn: customFilterFn +}) +``` + +### 初始全域篩選狀態 + +若需在表格初始化時設定初始全域篩選狀態,可透過 `initialState` 選項傳入。 + +但您也可以直接在 `state.globalFilter` 選項中指定初始狀態。 + +```jsx +const [globalFilter, setGlobalFilter] = useState("搜尋詞") //建議在此初始化 globalFilter 狀態 + +const table = useReactTable({ + // 其他選項... + initialState: { + globalFilter: '搜尋詞', // 若未管理 globalFilter 狀態,在此設定初始狀態 + } + state: { + globalFilter, // 將管理的 globalFilter 狀態傳遞給表格 + } +}) +``` + +> 注意:請勿同時使用 `initialState.globalFilter` 和 `state.globalFilter`,因為 `state.globalFilter` 的初始狀態會覆蓋 `initialState.globalFilter`。 + +### 停用全域篩選 + +預設情況下,所有欄位都啟用全域篩選。您可透過 `enableGlobalFilter` 表格選項停用所有欄位的全域篩選功能。也可透過將 `enableFilters` 表格選項設為 `false` 來同時停用欄位和全域篩選。 + +停用全域篩選後,`column.getCanGlobalFilter` API 將對該欄位回傳 `false`。 + +```jsx +const columns = [ + { + header: () => 'Id', + accessorKey: 'id', + enableGlobalFilter: false, // 停用此欄位的全域篩選 + }, + //... +] +//... +const table = useReactTable({ + // 其他選項... + columns, + enableGlobalFilter: false, // 停用所有欄位的全域篩選 +}) +``` diff --git a/docs/zh-hant/guide/grouping.md b/docs/zh-hant/guide/grouping.md new file mode 100644 index 0000000000..48eba09f34 --- /dev/null +++ b/docs/zh-hant/guide/grouping.md @@ -0,0 +1,148 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:06.316Z' +title: 分組 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [群組化](../framework/react/examples/grouping) + +## API + +[群組化 API](../api/features/grouping) + +## 群組化指南 + +有三種表格功能可以重新排序欄位,它們的執行順序如下: + +1. [欄位釘選 (Column Pinning)](../guide/column-pinning) - 若啟用釘選功能,欄位會被分割為左側、中間(未釘選)和右側釘選欄位。 +2. 手動 [欄位排序 (Column Ordering)](../guide/column-ordering) - 套用手動指定的欄位順序。 +3. **群組化** - 若啟用群組化功能、群組化狀態為啟用,且 `tableOptions.groupedColumnMode` 設為 `'reorder' | 'remove'`,則已群組化的欄位會被重新排序至欄位流的最前面。 + +TanStack Table 的群組化功能是針對欄位的特性,可讓您根據特定欄位對表格列進行分類與組織。當您有大量資料並希望根據特定條件將它們分組時,這項功能會非常實用。 + +要使用群組化功能,您需要使用群組化列模型 (grouped row model)。此模型負責根據群組化狀態來分組列。 + +```tsx +import { getGroupedRowModel } from '@tanstack/react-table' + +const table = useReactTable({ + // 其他選項... + getGroupedRowModel: getGroupedRowModel(), +}) +``` + +當群組化狀態為啟用時,表格會將符合條件的列作為子列 (subRows) 加入群組化列中。群組化列會被加入表格列的相同索引位置(與第一個符合條件的列相同)。符合條件的列會從表格列中移除。 +若要允許使用者展開與摺疊群組化列,您可以使用展開功能。 + +```tsx +import { getGroupedRowModel, getExpandedRowModel} from '@tanstack/react-table' + +const table = useReactTable({ + // 其他選項... + getGroupedRowModel: getGroupedRowModel(), + getExpandedRowModel: getExpandedRowModel(), +}) +``` + +### 群組化狀態 + +群組化狀態是一個字串陣列,每個字串代表要分組的欄位 ID。陣列中字串的順序決定了群組化的順序。例如,若群組化狀態為 ['column1', 'column2'],則表格會先根據 column1 分組,然後在每個群組內再根據 column2 分組。您可以使用 setGrouping 函式來控制群組化狀態: + +```tsx +table.setGrouping(['column1', 'column2']); +``` + +您也可以使用 resetGrouping 函式將群組化狀態重設為初始狀態: + +```tsx +table.resetGrouping(); +``` + +預設情況下,當欄位被群組化時,它會被移至表格的最前面。您可以使用 groupedColumnMode 選項來控制此行為。若設為 'reorder',則群組化欄位會被移至表格最前面。若設為 'remove',則群組化欄位會從表格中移除。若設為 false,則群組化欄位不會被移動或移除。 + +```tsx +const table = useReactTable({ + // 其他選項... + groupedColumnMode: 'reorder', +}) +``` + +### 聚合 + +當列被群組化時,您可以使用 aggregationFn 選項來聚合群組化列中的欄位資料。這是一個字串,代表聚合函式的 ID。您可以使用 aggregationFns 選項來定義聚合函式。 + +```tsx +const column = columnHelper.accessor('key', { + aggregationFn: 'sum', +}) +``` + +在上述範例中,sum 聚合函式會被用來聚合群組化列中的資料。 +預設情況下,數值欄位會使用 sum 聚合函式,非數值欄位會使用 count 聚合函式。您可以透過在欄位定義中指定 aggregationFn 選項來覆寫此行為。 + +以下是幾種內建的聚合函式: + +- sum - 計算群組化列中值的總和。 +- count - 計算群組化列中的列數。 +- min - 找出群組化列中的最小值。 +- max - 找出群組化列中的最大值。 +- extent - 找出群組化列中值的範圍(最小值和最大值)。 +- mean - 計算群組化列中值的平均值。 +- median - 找出群組化列中值的中位數。 +- unique - 回傳群組化列中的唯一值陣列。 +- uniqueCount - 計算群組化列中唯一值的數量。 + +#### 自訂聚合 + +當列被群組化時,您可以使用 aggregationFns 選項來聚合群組化列中的資料。這是一個記錄,其中鍵是聚合函式的 ID,值是聚合函式本身。接著您可以在欄位的 aggregationFn 選項中引用這些聚合函式。 + +```tsx +const table = useReactTable({ + // 其他選項... + aggregationFns: { + myCustomAggregation: (columnId, leafRows, childRows) => { + // 回傳聚合後的值 + }, + }, +}) +``` + +在上述範例中,myCustomAggregation 是一個自訂聚合函式,它接收欄位 ID、葉列 (leaf rows) 和子列 (child rows),並回傳聚合後的值。接著您可以在欄位的 aggregationFn 選項中使用此聚合函式: + +```tsx +const column = columnHelper.accessor('key', { + aggregationFn: 'myCustomAggregation', +}) +``` + +### 手動群組化 + +若您正在進行伺服器端群組化與聚合,可以透過 manualGrouping 選項啟用手動群組化。當此選項設為 true 時,表格不會自動使用 getGroupedRowModel() 來群組列,而是會預期您在將列傳遞給表格前手動進行群組化。 + +```tsx +const table = useReactTable({ + // 其他選項... + manualGrouping: true, +}) +``` + +> **注意:** 目前 TanStack Table 並沒有太多已知的簡單方法來實作伺服器端群組化。您需要進行大量的自訂儲存格渲染才能使其運作。 + +### 群組化變更處理器 + +若您想自行管理群組化狀態,可以使用 onGroupingChange 選項。此選項是一個函式,會在群組化狀態變更時被呼叫。您可以透過 tableOptions.state.grouping 選項將受控狀態傳回表格。 + +```tsx +const [grouping, setGrouping] = useState([]) + +const table = useReactTable({ + // 其他選項... + state: { + grouping: grouping, + }, + onGroupingChange: setGrouping +}) +``` diff --git a/docs/zh-hant/guide/header-groups.md b/docs/zh-hant/guide/header-groups.md new file mode 100644 index 0000000000..300eaa584d --- /dev/null +++ b/docs/zh-hant/guide/header-groups.md @@ -0,0 +1,50 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:20.109Z' +title: 標題群組 +--- +## API + +[Header Group API](../api/core/header-group) + +## 標題群組 (Header Groups) 指南 + +本快速指南將討論在 TanStack Table 中取得及操作標題群組物件 (header group objects) 的不同方式。 + +### 什麼是標題群組 (Header Groups)? + +標題群組 (Header Groups) 其實就是標題的「行 (rows)」。別被名稱迷惑,概念就是這麼簡單。絕大多數表格只會有一行標題(單一標題群組),但如果你像[欄位群組範例](../framework/react/examples/column-groups)那樣定義巢狀欄位結構,就可以擁有多行標題(多個標題群組)。 + +### 從何處取得標題群組 + +有多種 `table` 實例 API 可用來從表格實例中取得標題群組。`table.getHeaderGroups` 是最常用的 API,但根據你使用的功能,可能需要使用其他 API,例如若使用欄位固定 (column pinning) 功能時,就需要使用 `table.get[Left/Center/Right]HeaderGroups`。 + +### 標題群組物件 (Header Group Objects) + +標題群組物件與[行 (Row)](../guide/rows) 物件類似,但更簡單,因為標題行中的內容不像表格主體行那麼多。 + +預設情況下,標題群組只有三個屬性: + +- `id`:標題群組的唯一識別碼,由其深度(索引)產生。這在 React 元件中作為鍵 (key) 時很有用。 +- `depth`:標題群組的深度,以零為起始索引。可將其視為所有標題行中的行索引。 +- `headers`:屬於此標題群組(行)的[標題 (Header)](../guide/headers) 儲存格物件陣列。 + +### 存取標題儲存格 (Header Cells) + +要渲染標題群組中的標題儲存格,只需映射 (map) 標題群組物件中的 `headers` 陣列。 + +```jsx + + {table.getHeaderGroups().map(headerGroup => { + return ( + + {headerGroup.headers.map(header => ( // 映射 headerGroup 的 headers 陣列 + + {/* */} + + ))} + + ) + })} + +``` diff --git a/docs/zh-hant/guide/headers.md b/docs/zh-hant/guide/headers.md new file mode 100644 index 0000000000..7ae630de20 --- /dev/null +++ b/docs/zh-hant/guide/headers.md @@ -0,0 +1,86 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:39.084Z' +title: 標題 +--- +## API + +[Header API](../api/core/header) + +## 標頭指南 (Headers Guide) + +本快速指南將討論在 TanStack Table 中獲取及操作 `header` 物件的不同方式。 + +標頭 (headers) 相當於儲存格 (cells),但專用於表格的 `` 區段而非 `` 區段。 + +### 標頭來源 + +標頭來自[標頭群組 (Header Groups)](../guide/header-groups),其相當於資料列 (rows),但專用於表格的 `` 區段而非 `` 區段。 + +#### 標頭群組標頭 (HeaderGroup Headers) + +若處於標頭群組中,標頭會以陣列形式儲存在 `headerGroup.headers` 屬性中。通常您只需映射 (map) 此陣列即可渲染標頭。 + +```jsx + + {table.getHeaderGroups().map(headerGroup => { + return ( + + {headerGroup.headers.map(header => ( // 映射標頭群組的標頭陣列 + + {/* */} + + ))} + + ) + })} + +``` + +#### 標頭表格實例 API (Header Table Instance APIs) + +根據您使用的功能,有多種 `table` 實例 API 可用於取得標頭清單。最常用的可能是 `table.getFlatHeaders`,它會回傳表格中所有標頭的扁平化清單,但還有至少十幾種其他標頭 API 可搭配欄位可見性 (column visibility) 與欄位固定 (column pinning) 功能使用。例如 `table.getLeftLeafHeaders` 或 `table.getRightFlatHeaders` 等 API 可能依使用情境派上用場。 + +### 標頭物件 (Header Objects) + +標頭物件類似[儲存格 (Cells)](../guide/cells) 物件,但專用於表格的 `` 區段而非 `` 區段。每個標頭物件都可與 UI 中的 `` 或類似儲存格元素關聯。`header` 物件上有幾個屬性和方法可用於與表格狀態互動,並根據表格狀態提取儲存格值。 + +#### 標頭 ID (Header IDs) + +每個標頭物件都有 `id` 屬性,使其在表格實例中具有唯一性。通常您只需將此 `id` 作為 React 鍵值 (key) 的唯一識別符,或參考[高效欄位調整範例](../framework/react/examples/column-resizing-performant)時使用。 + +對於沒有進階巢狀或群組標頭邏輯的簡單標頭,`header.id` 會與其父級 `column.id` 相同。但若標頭屬於群組欄位或佔位儲存格,則會產生更複雜的 ID,由標頭家族、深度/標頭列索引、欄位 ID 和標頭群組 ID 組合而成。 + +#### 巢狀群組標頭屬性 (Nested Grouped Headers Properties) + +`header` 物件上有幾個屬性僅在標頭屬於巢狀或群組結構時有用,包括: + +- `colspan`:標頭應橫跨的欄位數,用於渲染 `` 元素的 `colSpan` 屬性。 +- `rowSpan`:標頭應縱跨的列數,用於渲染 `` 元素的 `rowSpan` 屬性。(目前 TanStack Table 預設未實作) +- `depth`:標頭群組所屬的「列索引」。 +- `isPlaceholder`:布林標記,若標頭為佔位標頭則為 true。佔位標頭用於填補欄位隱藏或屬於群組欄位時的空白。 +- `placeholderId`:佔位標頭的唯一識別符。 +- `subHeaders`:屬於此標頭的子標頭陣列。若標頭為葉節點標頭 (leaf header) 則為空。 + +> 注意:`header.index` 指其在標頭群組(標頭列)中的索引,即從左到右的位置。與 `header.depth`(標頭群組的「列索引」)不同。 + +#### 標頭父物件 (Header Parent Objects) + +每個標頭都儲存了對其父級[欄位 (column)](../guide/columns) 物件和父級[標頭群組 (header group)](../guide/header-groups) 物件的參照。 + +### 更多標頭 API (More Header APIs) + +標頭還有幾個實用的 API 可用於與表格狀態互動,大多與欄位尺寸調整 (Column sizing/resizing) 功能相關。詳見[欄位尺寸調整指南](../guide/column-sizing)。 + +### 標頭渲染 (Header Rendering) + +由於您定義的 `header` 欄位選項可以是字串、JSX 或回傳這兩者的函式,最佳渲染方式是使用適配器中的 `flexRender` 工具,它會為您處理所有情況。 + +```jsx +{headerGroup.headers.map(header => ( + + {/* 處理 `header` 欄位定義的所有可能情境 */} + {flexRender(header.column.columnDef.header, header.getContext())} + +))} +``` diff --git a/docs/zh-hant/guide/migrating.md b/docs/zh-hant/guide/migrating.md new file mode 100644 index 0000000000..ee6ccd2d82 --- /dev/null +++ b/docs/zh-hant/guide/migrating.md @@ -0,0 +1,196 @@ +--- +source-updated-at: '2024-12-30T21:50:15.000Z' +translation-updated-at: '2025-05-08T23:41:17.987Z' +title: 遷移至 V8 +--- +## 遷移至 V8 版本指南 + +TanStack Table V8 是從頭開始使用 TypeScript 全面重寫的 React Table v7。您的標記語言 (markup) 和 CSS 的整體結構/組織方式大致保持不變,但許多 API 已被重新命名或替換。 + +### 重要變更 + +- 全面改用 TypeScript 重寫,基礎套件已內含型別定義 +- 移除外掛系統,改採更多控制反轉 (inversion of control) 設計 +- 大幅擴充並改進的 API(以及新增如釘選 (pinning) 等功能) +- 更完善的受控狀態管理 +- 更佳的伺服器端操作 (server-side operations) 支援 +- 完整(但可選的)資料管道控制 +- 框架無關 (agnostic) 的核心,提供 React、Solid、Svelte、Vue 等框架適配器 (adapters),未來可能支援更多 +- 新的開發者工具 (Dev Tools) + +### 安裝新版本 + +新版本的 TanStack Table 發佈在 `@tanstack` 作用域下。請使用您喜歡的套件管理器安裝新套件: + +```bash +npm uninstall react-table @types/react-table +npm install @tanstack/react-table +``` + +```tsx +- import { useTable } from 'react-table' // [!code --] ++ import { useReactTable } from '@tanstack/react-table' // [!code ++] +``` + +型別定義現在已包含在基礎套件中,因此您可以移除 `@types/react-table` 套件。 + +> 如果需要,您可以保留舊版 `react-table` 套件安裝,以便逐步遷移程式碼。您應該能夠同時使用兩個套件來處理不同的表格而不會出現問題。 + +### 更新表格選項 + +- 將 `useTable` 重新命名為 `useReactTable` +- 舊的鉤子 (hook) 和外掛系統已被移除,取而代之的是針對每個功能的可樹搖 (tree-shakable) 行模型 (row model) 導入。 + +```tsx +- import { useTable, usePagination, useSortBy } from 'react-table'; // [!code --] ++ import { // [!code ++] ++ useReactTable, // [!code ++] ++ getCoreRowModel, // [!code ++] ++ getPaginationRowModel, // [!code ++] ++ getSortedRowModel // [!code ++] ++ } from '@tanstack/react-table'; // [!code ++] + +// ... + +- const tableInstance = useTable( // [!code --] +- { columns, data }, // [!code --] +- useSortBy, // [!code --] +- usePagination, //order of hooks used to matter // [!code --] +- // etc. // [!code --] +- ); // [!code --] ++ const tableInstance = useReactTable({ // [!code ++] ++ columns, // [!code ++] ++ data, // [!code ++] ++ getCoreRowModel: getCoreRowModel(), // [!code ++] ++ getPaginationRowModel: getPaginationRowModel(), // [!code ++] ++ getSortedRowModel: getSortedRowModel(), //order doesn't matter anymore! // [!code ++] ++ // etc. // [!code ++] ++ }); // [!code ++] +``` + +- 所有 `disable*` 表格選項已重新命名為 `enable*` 表格選項。(例如:`disableSortBy` 現在是 `enableSorting`,`disableGroupBy` 現在是 `enableGrouping`,依此類推。) +- ... + +### 更新欄位定義 + +- `accessor` 已重新命名為 `accessorKey` 或 `accessorFn`(取決於您使用的是字串還是函數) +- `width`、`minWidth`、`maxWidth` 已重新命名為 `size`、`minSize`、`maxSize` +- 可選地,您可以在每個欄位定義周圍使用新的 `createColumnHelper` 函數,以獲得更好的 TypeScript 提示。(如果您願意,仍然可以使用欄位定義的陣列。) + - 第一個參數是存取函數或存取字串。 + - 第二個參數是欄位選項的物件。 + +```tsx +const columns = [ +- { // [!code --] +- accessor: 'firstName', // [!code --] +- Header: 'First Name', // [!code --] +- }, // [!code --] +- { // [!code --] +- accessor: row => row.lastName, // [!code --] +- Header: () => Last Name, // [!code --] +- }, // [!code --] + +// 最佳 TypeScript 體驗,特別是在後續使用 `cell.getValue()` 時 ++ columnHelper.accessor('firstName', { //accessorKey // [!code ++] ++ header: 'First Name', // [!code ++] ++ }), // [!code ++] ++ columnHelper.accessor(row => row.lastName, { //accessorFn // [!code ++] ++ header: () => Last Name, // [!code ++] ++ }), // [!code ++] + +// 或(如果您偏好) ++ { // [!code ++] ++ accessorKey: 'firstName', // [!code ++] ++ header: 'First Name', // [!code ++] ++ }, // [!code ++] ++ { // [!code ++] ++ accessorFn: row => row.lastName, // [!code ++] ++ header: () => Last Name, // [!code ++] ++ }, // [!code ++] +] +``` + +> 注意:如果在元件內部定義欄位,您仍應嘗試為欄位定義提供穩定的識別資訊。這將有助於提升效能並避免不必要的重新渲染。請將欄位定義儲存在 `useMemo` 或 `useState` 鉤子中。 + +- 欄位選項名稱變更 + + - `Header` 已重新命名為 `header` + - `Cell` 已重新命名為 `cell`(單元格渲染函數也已變更。請參閱下文) + - `Footer` 已重新命名為 `footer` + - 所有 `disable*` 欄位選項已重新命名為 `enable*` 欄位選項。(例如:`disableSortBy` 現在是 `enableSorting`,`disableGroupBy` 現在是 `enableGrouping`,依此類推。) + - `sortType` 變更為 `sortingFn` + - ... + +- 自訂單元格渲染器的變更 + + - `value` 已重新命名為 `getValue`(在整個升級過程中,不再直接提供值,而是公開一個函數 `getValue` 來評估值。此變更旨在通過僅在呼叫 `getValue()` 時評估值並進行快取來提升效能。) + - `cell: { isGrouped, isPlaceholder, isAggregated }` 現在是 `cell: { getIsGrouped, getIsPlaceholder, getIsAggregated }` + - `column`:基礎層級的屬性現在是 RT 特定的。您在定義時添加到物件的值現在位於 `columnDef` 的下一層。 + - `table`:傳遞到 `useTable` 鉤子的屬性現在出現在 `options` 下。 + +### 遷移表格標記語言 + +- 使用 `flexRender()` 代替 `cell.render('Cell')` 或 `column.render('Header')` 等。 +- `getHeaderProps`、`getFooterProps`、`getCellProps`、`getRowProps` 等都已**棄用**。 + - TanStack Table 不再提供任何預設的 `style` 或無障礙屬性如 `role`。這些仍然很重要,但為了支援框架無關性,必須移除。 + - 您需要手動定義 `onClick` 處理程序,但有新的 `get*Handler` 輔助工具可以簡化此操作。 + - 您需要手動定義 `key` 屬性 + - 如果您使用需要 `colSpan` 的功能(如分組標頭、聚合等),則需要手動定義 `colSpan` 屬性 + +```tsx +- {cell.render('Header')} // [!code --] ++ // [!code ++] ++ {flexRender( // [!code ++] ++ header.column.columnDef.header, // [!code ++] ++ header.getContext() // [!code ++] ++ )} // [!code ++] ++ // [!code ++] +``` + +```tsx +- {cell.render('Cell')} // [!code --] ++ // [!code ++] ++ {flexRender( // [!code ++] ++ cell.column.columnDef.cell, // [!code ++] ++ cell.getContext() // [!code ++] ++ )} // [!code ++] ++ // [!code ++] +``` + +```tsx +// 在此情況下的欄位定義中 +- Header: ({ getToggleAllRowsSelectedProps }) => ( // [!code --] +- // [!code --] +- ), // [!code --] +- Cell: ({ row }) => ( // [!code --] +- // [!code --] +- ), // [!code --] ++ header: ({ table }) => ( // [!code ++] ++ // [!code ++] ++ ), // [!code ++] ++ cell: ({ row }) => ( // [!code ++] ++ // [!code ++] ++ ), // [!code ++] +``` + +### 其他變更 + +- 自訂的 `filterTypes`(現在稱為 `filterFns`)具有新的函數簽章,因為它僅返回一個布林值,表示是否應包含該行。 + +```tsx +- (rows: Row[], id: string, filterValue: any) => Row[] // [!code --] ++ (row: Row, id: string, filterValue: any) => boolean // [!code ++] +``` + +- ... + +> 本指南仍在完善中。如果您有時間,請考慮貢獻內容! diff --git a/docs/zh-hant/guide/pagination.md b/docs/zh-hant/guide/pagination.md new file mode 100644 index 0000000000..a2d5253227 --- /dev/null +++ b/docs/zh-hant/guide/pagination.md @@ -0,0 +1,223 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:05.008Z' +title: 分頁 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [分頁](../framework/react/examples/pagination) +- [受控分頁 (React Query)](../framework/react/examples/pagination-controlled) +- [可編輯資料](../framework/react/examples/editable-data) +- [展開](../framework/react/examples/expanding) +- [篩選](../framework/react/examples/filters) +- [完全受控](../framework/react/examples/fully-controlled) +- [列選取](../framework/react/examples/row-selection) + +## API + +[分頁 API](../api/features/pagination) + +## 分頁指南 + +TanStack Table 對客戶端分頁和伺服器端分頁都有良好的支援。本指南將帶您了解在表格中實作分頁的不同方式。 + +### 客戶端分頁 + +使用客戶端分頁意味著您取得的 `data` 將包含表格的***所有***列,表格實例將在前端處理分頁邏輯。 + +#### 是否應該使用客戶端分頁? + +客戶端分頁通常是使用 TanStack Table 實作分頁最簡單的方式,但對於非常大的資料集可能不太實際。 + +然而,許多人低估了客戶端能處理的資料量。如果您的表格永遠只有幾千列或更少,客戶端分頁仍然是一個可行的選擇。TanStack Table 設計用於處理數萬列的資料,在分頁、篩選、排序和分組方面仍能保持良好的效能。[官方分頁範例](../framework/react/examples/pagination) 載入了 100,000 列資料,效能依然良好,儘管只有少數幾欄。 + +每個使用情境都不同,取決於表格的複雜性、欄位數量、每筆資料的大小等。主要需要注意的瓶頸是: + +1. 您的伺服器能否在合理時間(和成本)內查詢所有資料? +2. 取得的資料總大小是多少?(如果您沒有太多欄位,這個問題可能沒有您想像的那麼嚴重。) +3. 如果一次性載入所有資料,客戶端瀏覽器是否會使用過多記憶體? + +如果不確定,您可以先從客戶端分頁開始,隨著資料增長再切換到伺服器端分頁。 + +#### 是否應該改用虛擬化? + +另一種選擇是不對資料分頁,而是在同一頁面上渲染大型資料集的所有列,但僅使用瀏覽器資源渲染視窗中可見的列。這種策略通常稱為「虛擬化 (virtualization)」或「視窗化 (windowing)」。TanStack 提供了一個虛擬化函式庫 [TanStack Virtual](https://tanstack.com/virtual/latest),可以與 TanStack Table 良好配合。虛擬化和分頁的 UI/UX 各有優缺點,請根據您的使用情境選擇最適合的方式。 + +#### 分頁列模型 + +如果想利用 TanStack Table 內建的客戶端分頁功能,首先需要傳入分頁列模型。 + +```jsx +import { useReactTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table'; +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), //載入客戶端分頁程式碼 +}); +``` + +### 手動伺服器端分頁 + +如果決定需要使用伺服器端分頁,以下是實作方式。 + +伺服器端分頁不需要分頁列模型,但如果您在共享元件中為其他需要它的表格提供了該模型,仍可以通過將 `manualPagination` 選項設為 `true` 來關閉客戶端分頁。將 `manualPagination` 設為 `true` 會告訴表格實例在底層使用 `table.getPrePaginationRowModel` 列模型,並假設您傳入的 `data` 已經過分頁。 + +#### 頁數和列數 + +表格實例無法知道後端總共有多少列/頁,除非您告訴它。提供 `rowCount` 或 `pageCount` 表格選項,讓表格實例知道總共有多少頁。如果提供 `rowCount`,表格實例會根據 `rowCount` 和 `pageSize` 內部計算 `pageCount`。或者,如果您已經知道頁數,可以直接提供 `pageCount`。如果不知道頁數,可以傳入 `-1` 作為 `pageCount`,但在這種情況下,`getCanNextPage` 和 `getCanPreviousPage` 列模型函式將始終返回 `true`。 + +```jsx +import { useReactTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table'; +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + // getPaginationRowModel: getPaginationRowModel(), //伺服器端分頁不需要 + manualPagination: true, //關閉客戶端分頁 + rowCount: dataQuery.data?.rowCount, //傳入總列數,讓表格知道有多少頁(如果未提供 pageCount,則內部計算) + // pageCount: dataQuery.data?.pageCount, //或者直接傳入 pageCount 代替 rowCount +}); +``` + +> **注意**:將 `manualPagination` 選項設為 `true` 會讓表格實例假設您傳入的 `data` 已經過分頁。 + +### 分頁狀態 + +無論您使用的是客戶端還是手動伺服器端分頁,都可以使用內建的 `pagination` 狀態和 API。 + +`pagination` 狀態是一個物件,包含以下屬性: + +- `pageIndex`:當前頁面索引(從零開始)。 +- `pageSize`:當前頁面大小。 + +您可以像管理表格實例中的其他狀態一樣管理 `pagination` 狀態。 + +```jsx +import { useReactTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table'; +//... +const [pagination, setPagination] = useState({ + pageIndex: 0, //初始頁面索引 + pageSize: 10, //預設頁面大小 +}); + +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onPaginationChange: setPagination, //當內部 API 變更分頁狀態時更新分頁狀態 + state: { + //... + pagination, + }, +}); +``` + +或者,如果不需要在自己的作用域中管理 `pagination` 狀態,但需要為 `pageIndex` 和 `pageSize` 設置不同的初始值,可以使用 `initialState` 選項。 + +```jsx +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + initialState: { + pagination: { + pageIndex: 2, //自訂初始頁面索引 + pageSize: 25, //自訂預設頁面大小 + }, + }, +}); +``` + +> **注意**:請勿同時將 `pagination` 狀態傳遞給 `state` 和 `initialState` 選項。`state` 會覆蓋 `initialState`。僅使用其中之一。 + +### 分頁選項 + +除了對手動伺服器端分頁有用的 `manualPagination`、`pageCount` 和 `rowCount` 選項(已在[上文](#手動伺服器端分頁)討論)外,還有一個表格選項值得了解。 + +#### 自動重置頁面索引 + +預設情況下,當發生影響頁面的狀態變更時(例如 `data` 更新、篩選變更、分組變更等),`pageIndex` 會重置為 `0`。當 `manualPagination` 為 true 時,此行為會自動停用,但可以通過明確為 `autoResetPageIndex` 表格選項賦予布林值來覆蓋。 + +```jsx +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + autoResetPageIndex: false, //關閉 pageIndex 的自動重置 +}); +``` + +但請注意,如果關閉 `autoResetPageIndex`,可能需要添加一些邏輯來自行處理 `pageIndex` 的重置,以避免顯示空白頁面。 + +### 分頁 API + +有幾個分頁表格實例 API 可用於連接您的分頁 UI 元件。 + +#### 分頁按鈕 API + +- `getCanPreviousPage`:用於在第一頁時停用「上一頁」按鈕。 +- `getCanNextPage`:用於在沒有更多頁面時停用「下一頁」按鈕。 +- `previousPage`:用於前往上一頁。(按鈕點擊處理器) +- `nextPage`:用於前往下一頁。(按鈕點擊處理器) +- `firstPage`:用於前往第一頁。(按鈕點擊處理器) +- `lastPage`:用於前往最後一頁。(按鈕點擊處理器) +- `setPageIndex`:用於「前往頁面」輸入框。 +- `resetPageIndex`:用於將表格狀態重置為原始頁面索引。 +- `setPageSize`:用於「頁面大小」輸入/選擇框。 +- `resetPageSize`:用於將表格狀態重置為原始頁面大小。 +- `setPagination`:用於一次性設置所有分頁狀態。 +- `resetPagination`:用於將表格狀態重置為原始分頁狀態。 + +> **注意**:其中一些 API 是 `v8.13.0` 新增的。 + +```jsx + + + + + +``` + +#### 分頁資訊 API + +- `getPageCount`:用於顯示總頁數。 +- `getRowCount`:用於顯示總列數。 diff --git a/docs/zh-hant/guide/pinning.md b/docs/zh-hant/guide/pinning.md new file mode 100644 index 0000000000..dc7ff796c1 --- /dev/null +++ b/docs/zh-hant/guide/pinning.md @@ -0,0 +1,11 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:39:36.096Z' +title: Pinning Guide +--- + + +釘選 (Pinning) 功能分為兩種不同的操作指南: + +- [欄位釘選 (Column Pinning)](../guide/column-pinning) +- [列釘選 (Row Pinning)](../guide/row-pinning) diff --git a/docs/zh-hant/guide/row-models.md b/docs/zh-hant/guide/row-models.md new file mode 100644 index 0000000000..f179b7df01 --- /dev/null +++ b/docs/zh-hant/guide/row-models.md @@ -0,0 +1,123 @@ +--- +source-updated-at: '2024-04-24T03:41:47.000Z' +translation-updated-at: '2025-05-08T23:40:28.433Z' +title: 行模型 +--- +## 行模型 (Row Models) 指南 + +如果你查看 TanStack Table 最基本的範例,你會看到像這樣的程式碼片段: + +```ts +import { getCoreRowModel, useReactTable } from '@tanstack/react-table' + +function Component() { + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), //row model + }) +} +``` + +這個 `getCoreRowModel` 函式是什麼?為什麼你需要從 TanStack Table 導入它,然後又直接傳回給它自己? + +答案是 TanStack Table 是一個模組化的函式庫。並非所有功能的程式碼都會預設包含在 createTable 函式/鉤子 (hooks) 中。你只需要導入並包含那些根據你想使用的功能來正確生成行 (rows) 所需的程式碼。 + +### 什麼是行模型 (Row Models)? + +行模型在 TanStack Table 的底層運行,以有用的方式轉換你的原始數據,這些轉換對於數據網格 (data grid) 功能(如篩選、排序、分組、展開和分頁)是必需的。最終生成並渲染在螢幕上的行,不一定會與你傳遞給表格的原始數據形成 1:1 的映射關係。它們可能經過排序、篩選、分頁等處理。 + +### 導入行模型 + +你應該只導入你需要的行模型。以下是所有可用的行模型: + +```ts +//只導入你需要的行模型 +import { + getCoreRowModel, + getExpandedRowModel, + getFacetedMinMaxValues, + getFacetedRowModel, + getFacetedUniqueValues, + getFilteredRowModel, + getGroupedRowModel, + getPaginationRowModel, + getSortedRowModel, +} +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getExpandedRowModel: getExpandedRowModel(), + getFacetedMinMaxValues: getFacetedMinMaxValues(), + getFacetedRowModel: getFacetedRowModel(), + getFacetedUniqueValues: getFacetedUniqueValues(), + getFilteredRowModel: getFilteredRowModel(), + getGroupedRowModel: getGroupedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), +}) +``` + +### 自訂/分叉行模型 + +你不一定要使用 TanStack Table 提供的確切行模型。如果你需要對某些行模型進行進階自訂,可以自由複製你想要自訂的行模型的[原始碼](https://github.com/TanStack/table/tree/main/packages/table-core/src/utils),並根據你的需求進行修改。 + +### 使用行模型 + +一旦你的表格實例 (table instance) 被創建,你可以直接從表格實例中存取所有你可能需要的行模型。除了你可能導入的行模型之外,還有更多衍生的行模型可供使用。 + +對於一般的渲染使用情境,你可能只需要使用 `table.getRowModel()` 方法,因為這個行模型會根據你啟用或停用的功能,使用所有/任何其他行模型。所有其他行模型都可以讓你「深入挖掘」表格中正在發生的底層數據轉換。 + +### 表格實例上可用的行模型 + +- **`getRowModel`** - 這是你應該用於渲染表格行標記 (markup) 的主要行模型。它會使用所有其他行模型來生成最終的行模型,你將使用它來渲染表格行。 + +- `getCoreRowModel` - 返回一個基本的行模型,它只是與傳遞給表格的原始數據形成 1:1 的映射關係。 + +- `getFilteredRowModel` - 返回一個考慮了欄位篩選和全域篩選的行模型。 +- `getPreFilteredRowModel` - 返回一個在應用欄位篩選和全域篩選之前的行模型。 + +- `getGroupedRowModel` - 返回一個對數據應用分組和聚合並創建子行的行模型。 +- `getPreGroupedRowModel` - 返回一個在應用分組和聚合之前的行模型。 + +- `getSortedRowModel` - 返回一個已應用排序的行模型。 +- `getPreSortedRowModel` - 返回一個在應用排序之前的行模型(行保持原始順序)。 + +- `getExpandedRowModel` - 返回一個考慮了展開/隱藏子行的行模型。 +- `getPreExpandedRowModel` - 返回一個僅包含根層級行且不包含展開子行的行模型。仍然包含排序。 + +- `getPaginationRowModel` - 返回一個僅包含基於分頁狀態應該顯示在當前頁面上的行的行模型。 +- `getPrePaginationRowModel` - 返回一個未應用分頁的行模型(包含所有行)。 + +- `getSelectedRowModel` - 返回所有選中行的行模型(但僅基於傳遞給表格的數據)。在 getCoreRowModel 之後運行。 +- `getPreSelectedRowModel` - 返回一個在應用行選擇之前的行模型(僅返回 getCoreRowModel)。 +- `getGroupedSelectedRowModel` - 返回分組後選中行的行模型。在 getSortedRowModel 之後運行,而 getSortedRowModel 在 getGroupedRowModel 之後運行,getGroupedRowModel 又在 getFilteredRowModel 之後運行。 +- `getFilteredSelectedRowModel` - 返回在應用欄位篩選和全域篩選後選中行的行模型。在 getFilteredRowModel 之後運行。 + +### 行模型執行的順序 + +了解 TanStack Table 如何在內部處理行,可以幫助你更好地理解底層發生的情況,並幫助你調試可能遇到的問題。 + +在內部,如果相應的功能被啟用,行模型會按照以下順序應用於數據: + +`getCoreRowModel` -> `getFilteredRowModel` -> `getGroupedRowModel` -> `getSortedRowModel` -> `getExpandedRowModel` -> `getPaginationRowModel` -> `getRowModel` + +如果在任何情況下,相應的功能被停用或通過 `"manual*"` 表格選項關閉,則在該處理步驟中會改用 `getPre*RowModel`。 + +如上所示,數據首先被篩選,然後分組,接著排序,然後展開,最後進行分頁作為最終步驟。 + +### 行模型的數據結構 + +每個行模型都會以 3 種不同的有用格式提供行: + +1. `rows` - 行的陣列。 +2. `flatRows` - 行的陣列,但所有子行都被扁平化到頂層。 +3. `rowsById` - 行的物件,其中每個行都以其 `id` 作為鍵。這對於通過 `id` 快速查找行並獲得更好的性能非常有用。 + +```ts +console.log(table.getRowModel().rows) // 行的陣列 +console.log(table.getRowModel().flatRows) // 行的陣列,但所有子行都被扁平化到頂層 +console.log(table.getRowModel().rowsById['row-id']) // 行的物件,其中每個行都以其 `id` 作為鍵 +``` diff --git a/docs/zh-hant/guide/row-pinning.md b/docs/zh-hant/guide/row-pinning.md new file mode 100644 index 0000000000..7bc0f281ca --- /dev/null +++ b/docs/zh-hant/guide/row-pinning.md @@ -0,0 +1,21 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:39:30.624Z' +title: 行固定 +--- +## 範例 + +想要直接查看實作方式嗎?請參考以下範例: + +- [row-pinning](../framework/react/examples/row-pinning) + +## API + +[行固定 API](../api/features/row-pinning) + +## 行固定指南 + +有 2 種表格功能可以重新排序行,其執行順序如下: + +1. **行固定 (Row Pinning)** - 若啟用固定功能,行會被分割為頂部固定行、中部(未固定)行和底部固定行。 +2. [排序](../guide/sorting) diff --git a/docs/zh-hant/guide/row-selection.md b/docs/zh-hant/guide/row-selection.md new file mode 100644 index 0000000000..65d15565b8 --- /dev/null +++ b/docs/zh-hant/guide/row-selection.md @@ -0,0 +1,185 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:26.362Z' +title: 行選擇 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [React 行選取](../framework/react/examples/row-selection) +- [Vue 行選取](../framework/vue/examples/row-selection) +- [React 展開](../framework/react/examples/expanding) + +## API + +[行選取 API](../api/features/row-selection) + +## 行選取指南 + +行選取功能會追蹤哪些行被選取,並允許你以多種方式切換行的選取狀態。讓我們來看看一些常見的使用情境。 + +### 存取行選取狀態 + +表格實例已為你管理行選取狀態(不過如後文所示,在自己的作用域中管理行選取狀態可能更方便)。你可以透過幾個 API 存取內部行選取狀態或已選取的行。 + +- `getState().rowSelection` - 回傳內部行選取狀態 +- `getSelectedRowModel()` - 回傳已選取的行 +- `getFilteredSelectedRowModel()` - 回傳過濾後的已選取行 +- `getGroupedSelectedRowModel()` - 回傳分組和排序後的已選取行 + +```ts +console.log(table.getState().rowSelection) //取得行選取狀態 - { 1: true, 2: false, etc... } +console.log(table.getSelectedRowModel().rows) //取得完整的客戶端已選取行 +console.log(table.getFilteredSelectedRowModel().rows) //取得過濾後的客戶端已選取行 +console.log(table.getGroupedSelectedRowModel().rows) //取得分組後的客戶端已選取行 +``` + +> 注意:如果你使用 `manualPagination`,請注意 `getSelectedRowModel` API 只會回傳當前頁面上的已選取行,因為表格行模型只能基於傳入的 `data` 生成行。不過,行選取狀態可以包含不在 `data` 陣列中的行 ID。 + +### 管理行選取狀態 + +儘管表格實例已為你管理行選取狀態,但通常更方便自行管理狀態,以便輕鬆存取已選取的行 ID,用於 API 呼叫或其他操作。 + +使用 `onRowSelectionChange` 表格選項將行選取狀態提升到自己的作用域。然後透過 `state` 表格選項將行選取狀態傳回表格實例。 + +```ts +const [rowSelection, setRowSelection] = useState({}) //自行管理行選取狀態 + +const table = useReactTable({ + //... + onRowSelectionChange: setRowSelection, //將行選取狀態提升到自己的作用域 + state: { + rowSelection, //將行選取狀態傳回表格實例 + }, +}) +``` + +### 實用的行 ID + +預設情況下,每行的 ID 僅為 `row.index`。如果你使用行選取功能,很可能會希望使用更有用的行識別符,因為行選取狀態是以行 ID 為鍵。你可以使用 `getRowId` 表格選項指定一個函式,為每行回傳唯一的行 ID。 + +```ts +const table = useReactTable({ + //... + getRowId: row => row.uuid, //使用資料庫中的行 uuid 作為行 ID +}) +``` + +現在,當行被選取時,行選取狀態會如下所示: + +```json +{ + "13e79140-62a8-4f9c-b087-5da737903b76": true, + "f3e2a5c0-5b7a-4d8a-9a5c-9c9b8a8e5f7e": false + //... +} +``` + +而不是這樣: + +```json +{ + "0": true, + "1": false + //... +} +``` + +### 條件式啟用行選取 + +預設情況下,所有行都啟用行選取。若要為特定行條件式啟用行選取,或為所有行禁用行選取,你可以使用 `enableRowSelection` 表格選項,它接受布林值或函式以進行更細粒度的控制。 + +```ts +const table = useReactTable({ + //... + enableRowSelection: row => row.original.age > 18, //僅為成年人啟用行選取 +}) +``` + +要在 UI 中強制執行行是否可選取,你可以使用 `row.getCanSelect()` API 來檢查核取方塊或其他選取 UI。 + +### 單行選取 + +預設情況下,表格允許多行同時選取。但如果只想允許一次選取單行,可以將 `enableMultiRowSelection` 表格選項設為 `false` 以禁用多行選取,或傳入函式以條件式禁用行的子行多行選取。 + +這對於製作具有單選按鈕而非核取方塊的表格很有用。 + +```ts +const table = useReactTable({ + //... + enableMultiRowSelection: false, //僅允許一次選取單行 + // enableMultiRowSelection: row => row.original.age > 18, //僅為成年人允許一次選取單行 +}) +``` + +### 子行選取 + +預設情況下,選取父行會選取其所有子行。如果你想禁用自動子行選取,可以將 `enableSubRowSelection` 表格選項設為 `false` 以禁子行選取,或傳入函式以條件式禁用行的子行選取。 + +```ts +const table = useReactTable({ + //... + enableSubRowSelection: false, //禁子行選取 + // enableSubRowSelection: row => row.original.age > 18, //為成年人禁子行選取 +}) +``` + +### 渲染行選取 UI + +TanStack Table 不規定你應如何渲染行選取 UI。你可以使用核取方塊、單選按鈕,或簡單地將點擊事件綁定到行本身。表格實例提供了一些 API 來幫助你渲染行選取 UI。 + +#### 將行選取 API 連接到核取方塊輸入 + +TanStack Table 提供了一些處理函式,你可以直接將其連接到核取方塊輸入,以便輕鬆切換行選取。這些函式會自動呼叫其他內部 API 來更新行選取狀態並重新渲染表格。 + +使用 `row.getToggleSelectedHandler()` API 連接到核取方塊輸入以切換行的選取狀態。 + +使用 `table.getToggleAllRowsSelectedHandler()` 或 `table.getToggleAllPageRowsSelectedHandler` API 連接到「全選」核取方塊輸入以切換所有行的選取狀態。 + +如果需要對這些處理函式進行更細粒度的控制,你可以直接使用 `row.toggleSelected()` 或 `table.toggleAllRowsSelected()` API。甚至可以直接呼叫 `table.setRowSelection()` API 來直接設定行選取狀態,就像使用任何其他狀態更新器一樣。這些處理函式僅為便利性而提供。 + +```tsx +const columns = [ + { + id: 'select-col', + header: ({ table }) => ( + + ), + cell: ({ row }) => ( + + ), + }, + //... 更多欄位定義... +] +``` + +#### 將行選取 API 連接到 UI + +如果你想要更簡單的行選取 UI,可以將點擊事件綁定到行本身。`row.getToggleSelectedHandler()` API 也適用於此情境。 + +```tsx + + {table.getRowModel().rows.map(row => { + return ( + + {row.getVisibleCells().map(cell => { + return {/* */} + })} + + ) + })} + +``` diff --git a/docs/zh-hant/guide/rows.md b/docs/zh-hant/guide/rows.md new file mode 100644 index 0000000000..f435a2dba5 --- /dev/null +++ b/docs/zh-hant/guide/rows.md @@ -0,0 +1,98 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:39:56.859Z' +title: 行 +--- +## API + +[Row API](../api/core/row) + +## 行 (Rows) 指南 + +本快速指南將討論在 TanStack Table 中獲取及與行物件 (row objects) 互動的不同方式。 + +### 獲取行的來源 + +有多種 `table` 實例 API 可用於從表格實例中檢索行。 + +#### table.getRow + +如果需要透過 `id` 存取特定行,可以使用 `table.getRow` 表格實例 API。 + +```js +const row = table.getRow(rowId) +``` + +#### 行模型 (Row Models) + +`table` 實例會生成 `row` 物件並將其儲存在稱為 ["行模型 (Row Models)"](../guide/row-models) 的實用陣列中。這在 [行模型指南](../guide/row-models) 中有更詳細的討論,以下是存取行模型最常見的方式。 + +##### 渲染行 (Render Rows) + +```jsx + + {table.getRowModel().rows.map(row => ( + + {/* ... */} + + ))} + +``` + +##### 獲取選中的行 (Get Selected Rows) + +```js +const selectedRows = table.getSelectedRowModel().rows +``` + +### 行物件 (Row Objects) + +每個行物件都包含行資料和許多 API,這些 API 可用於與表格狀態互動或根據表格狀態從行中提取儲存格 (cells)。 + +#### 行 ID (Row IDs) + +每個行物件都有一個 `id` 屬性,使其在表格實例中唯一。預設情況下 `row.id` 與行模型中建立的 `row.index` 相同。然而,用行資料中的唯一識別碼覆蓋每行的 `id` 會很有用。可以使用 `getRowId` 表格選項來實現這一點。 + +```js +const table = useReactTable({ + columns, + data, + getRowId: originalRow => originalRow.uuid, // 使用原始行資料中的 uuid 覆蓋 row.id +}) +``` + +> 注意:在某些功能如分組 (grouping) 和展開 (expanding) 中,`row.id` 會附加額外的字串。 + +#### 存取行值 (Access Row Values) + +存取行中資料值的推薦方式是使用 `row.getValue` 或 `row.renderValue` API。使用這些 API 會快取存取器函數 (accessor functions) 的結果,保持渲染效率。兩者唯一的區別在於,`row.renderValue` 會返回值或 `renderFallbackValue`(如果值為 undefined),而 `row.getValue` 會返回值或 `undefined`(如果值為 undefined)。 + +```js +// 從任何欄位存取資料 +const firstName = row.getValue('firstName') // 從 firstName 欄位讀取行值 +const renderedLastName = row.renderValue('lastName') // 渲染 lastName 欄位的值 +``` + +> 注意:`cell.getValue` 和 `cell.renderValue` 分別是 `row.getValue` 和 `row.renderValue` API 的快捷方式。 + +#### 存取原始行資料 (Access Original Row Data) + +對於每個行物件,可以透過 `row.original` 屬性存取傳遞給表格實例的原始對應 `data`。`row.original` 中的任何資料都不會被欄位定義中的存取器修改,因此如果在存取器中進行了任何資料轉換,這些轉換不會反映在 `row.original` 物件中。 + +```js +// 存取原始行中的任何資料 +const firstName = row.original.firstName // { firstName: 'John', lastName: 'Doe' } +``` + +### 子行 (Sub Rows) + +如果使用分組或展開功能,行可能包含子行或父行參考。這在 [展開指南](../guide/expanding) 中有更詳細的討論,以下是處理子行的有用屬性和方法的快速概述。 + +- `row.subRows`: 行的子行陣列。 +- `row.depth`: 行相對於根行陣列的深度(如果嵌套或分組)。根級行為 0,子行為 1,孫行為 2,依此類推。 +- `row.parentId`: 行的父行的唯一 ID(包含此行的父行的 subRows 陣列)。 +- `row.getParentRow`: 返回行的父行(如果存在)。 + +### 更多行 API (More Row APIs) + +根據表格使用的功能,還有數十個用於與行互動的有用 API。詳情請參閱各功能的相應 API 文件或指南。 diff --git a/docs/zh-hant/guide/sorting.md b/docs/zh-hant/guide/sorting.md new file mode 100644 index 0000000000..a91332604b --- /dev/null +++ b/docs/zh-hant/guide/sorting.md @@ -0,0 +1,415 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:41:46.699Z' +title: 排序 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [排序](../framework/react/examples/sorting) +- [篩選器](../framework/react/examples/filters) + +## API + +[排序 API](../api/features/sorting) + +## 排序指南 + +TanStack Table 提供了適用於各種排序需求的解決方案。本指南將帶您了解各種選項,用於自訂內建的客戶端排序功能,以及如何選擇不使用客戶端排序,改用手動的伺服器端排序。 + +### 排序狀態 + +排序狀態定義為一個物件陣列,結構如下: + +```tsx +type ColumnSort = { + id: string + desc: boolean +} +type SortingState = ColumnSort[] +``` + +由於排序狀態是一個陣列,因此可以同時對多個欄位進行排序。更多關於多重排序的自訂選項請參閱[下方](#multi-sorting)。 + +#### 存取排序狀態 + +您可以直接從表格實例中存取排序狀態,就像使用 `table.getState()` API 存取其他狀態一樣。 + +```tsx +const table = useReactTable({ + columns, + data, + //... +}) + +console.log(table.getState().sorting) // 從表格實例中存取排序狀態 +``` + +然而,如果您需要在表格初始化之前存取排序狀態,可以像下方所示「控制」排序狀態。 + +#### 受控排序狀態 + +如果您需要輕鬆存取排序狀態,可以使用 `state.sorting` 和 `onSortingChange` 表格選項,在您自己的狀態管理中控制/管理排序狀態。 + +```tsx +const [sorting, setSorting] = useState([]) // 可以在這裡設定初始排序狀態 +//... +// 使用排序狀態從伺服器獲取資料或其他操作... +//... +const table = useReactTable({ + columns, + data, + //... + state: { + sorting, + }, + onSortingChange: setSorting, +}) +``` + +#### 初始排序狀態 + +如果您不需要在自己的狀態管理或作用域中控制排序狀態,但仍想設定初始排序狀態,可以使用 `initialState` 表格選項,而不是 `state`。 + +```jsx +const table = useReactTable({ + columns, + data, + //... + initialState: { + sorting: [ + { + id: 'name', + desc: true, // 預設按名稱降序排序 + }, + ], + }, +}) +``` + +> **注意**:請勿同時使用 `initialState.sorting` 和 `state.sorting`,因為 `state.sorting` 中的初始化狀態會覆蓋 `initialState.sorting`。 + +### 客戶端 vs 伺服器端排序 + +是否應該使用客戶端或伺服器端排序,完全取決於您是否同時使用客戶端或伺服器端分頁或篩選。請保持一致,因為在伺服器端分頁或篩選的情況下使用客戶端排序,只會對當前載入的資料進行排序,而不是整個資料集。 + +### 手動伺服器端排序 + +如果您計劃僅在後端邏輯中使用自己的伺服器端排序,則不需要提供排序行模型。但如果您已提供排序行模型,卻想停用它,可以使用 `manualSorting` 表格選項。 + +```jsx +const [sorting, setSorting] = useState([]) +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + //getSortedRowModel: getSortedRowModel(), //手動排序不需要此選項 + manualSorting: true, //使用預先排序的行模型,而非排序行模型 + state: { + sorting, + }, + onSortingChange: setSorting, +}) +``` + +> **注意**:當 `manualSorting` 設為 `true` 時,表格會假設您提供的資料已經排序,不會對其進行任何排序操作。 + +### 客戶端排序 + +要實現客戶端排序,首先需要向表格提供排序行模型。您可以從 TanStack Table 導入 `getSortedRowModel` 函數,它將用於將您的行轉換為已排序的行。 + +```jsx +import { useReactTable } from '@tanstack/react-table' +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), //提供排序行模型 +}) +``` + +### 排序函數 + +所有欄位的預設排序函數是根據欄位的資料類型推斷的。然而,為特定欄位定義確切的排序函數可能會很有用,尤其是當您的資料包含可為空的值或非標準資料類型時。 + +您可以使用 `sortingFn` 欄位選項,在每個欄位的基礎上確定自訂排序函數。 + +預設情況下,有 6 種內建排序函數可供選擇: + +- `alphanumeric` - 不區分大小寫地按混合字母數字值排序。速度較慢,但如果您的字串包含需要自然排序的數字,則更準確。 +- `alphanumericCaseSensitive` - 區分大小寫地按混合字母數字值排序。速度較慢,但如果您的字串包含需要自然排序的數字,則更準確。 +- `text` - 不區分大小寫地按文字/字串值排序。速度較快,但如果您的字串包含需要自然排序的數字,則準確性較低。 +- `textCaseSensitive` - 區分大小寫地按文字/字串值排序。速度較快,但如果您的字串包含需要自然排序的數字,則準確性較低。 +- `datetime` - 按時間排序,如果您的值是 `Date` 物件,請使用此選項。 +- `basic` - 使用基本的/標準的 `a > b ? 1 : a < b ? -1 : 0` 比較進行排序。這是最快的排序函數,但可能不是最準確的。 + +您也可以將自訂排序函數定義為 `sortingFn` 欄位選項,或作為全域排序函數使用 `sortingFns` 表格選項。 + +#### 自訂排序函數 + +在 `sortingFns` 表格選項或 `sortingFn` 欄位選項中定義自訂排序函數時,應具有以下簽名: + +```tsx +//可選地使用 SortingFn 來推斷參數類型 +const myCustomSortingFn: SortingFn = (rowA: Row, rowB: Row, columnId: string) => { + return //-1、0 或 1 - 使用 rowA.original 和 rowB.original 存取任何行資料 +} +``` + +> 注意:比較函數不需要考慮欄位是降序還是升序。行模型會處理該邏輯。`sortingFn` 函數只需提供一致的比較。 + +每個排序函數接收 2 行和一個欄位 ID,並預期使用欄位 ID 比較這兩行,以返回 `-1`、`0` 或 `1` 的升序結果。以下是速查表: + +| 返回值 | 升序順序 | +| ------ | --------------- | +| `-1` | `a < b` | +| `0` | `a === b` | +| `1` | `a > b` | + +```jsx +const columns = [ + { + header: () => 'Name', + accessorKey: 'name', + sortingFn: 'alphanumeric', // 按名稱使用內建排序函數 + }, + { + header: () => 'Age', + accessorKey: 'age', + sortingFn: 'myCustomSortingFn', // 使用自訂全域排序函數 + }, + { + header: () => 'Birthday', + accessorKey: 'birthday', + sortingFn: 'datetime', // 推薦用於日期欄位 + }, + { + header: () => 'Profile', + accessorKey: 'profile', + // 直接使用自訂排序函數 + sortingFn: (rowA, rowB, columnId) => { + return rowA.original.someProperty - rowB.original.someProperty + }, + } +] +//... +const table = useReactTable({ + columns, + data, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + sortingFns: { //新增自訂排序函數 + myCustomSortingFn: (rowA, rowB, columnId) => { + return rowA.original[columnId] > rowB.original[columnId] ? 1 : rowA.original[columnId] < rowB.original[columnId] ? -1 : 0 + }, + }, +}) +``` + +### 自訂排序 + +有許多表格和欄位選項可用於進一步自訂排序的使用者體驗和行為。 + +#### 停用排序 + +您可以使用 `enableSorting` 欄位選項或表格選項,停用特定欄位或整個表格的排序功能。 + +```jsx +const columns = [ + { + header: () => 'ID', + accessorKey: 'id', + enableSorting: false, // 停用此欄位的排序 + }, + { + header: () => 'Name', + accessorKey: 'name', + }, + //... +] +//... +const table = useReactTable({ + columns, + data, + enableSorting: false, // 停用整個表格的排序 +}) +``` + +#### 排序方向 + +預設情況下,使用 `toggleSorting` API 循環切換欄位排序時,第一個排序方向對於字串欄位是升序,對於數字欄位是降序。您可以使用 `sortDescFirst` 欄位選項或表格選項更改此行為。 + +```jsx +const columns = [ + { + header: () => 'Name', + accessorKey: 'name', + sortDescFirst: true, // 名稱欄位預設按降序排序(字串欄位預設為升序) + }, + { + header: () => 'Age', + accessorKey: 'age', + sortDescFirst: false, // 年齡欄位預設按升序排序(數字欄位預設為降序) + }, + //... +] +//... +const table = useReactTable({ + columns, + data, + sortDescFirst: true, // 所有欄位預設按降序排序(字串欄位預設為升序,數字欄位預設為降序) +}) +``` + +> **注意**:對於包含可空值的欄位,您可能需要明確設定 `sortDescFirst` 欄位選項。如果欄位包含可空值,表格可能無法正確判斷該欄位是數字還是字串。 + +#### 反轉排序 + +反轉排序與更改預設排序方向不同。如果欄位的 `invertSorting` 選項設為 `true`,則「降序/升序」排序狀態仍會正常循環,但實際的行排序會被反轉。這對於具有反向最佳/最差比例的值很有用,例如排名(第1、第2、第3)或類似高爾夫的計分。 + +```jsx +const columns = [ + { + header: () => 'Rank', + accessorKey: 'rank', + invertSorting: true, // 反轉此欄位的排序。即使應用「降序」排序,也會是 1st -> 2nd -> 3rd -> ... + }, + //... +] +``` + +#### 排序未定義值 + +任何未定義的值將根據 `sortUndefined` 欄位選項或表格選項,排序到列表的開頭或結尾。您可以根據具體使用情況自訂此行為。 + +如果未指定,`sortUndefined` 的預設值為 `1`,未定義的值將以較低優先級排序(降序),如果是升序,未定義的值將出現在列表的末尾。 + +- `'first'` - 未定義的值將被推到列表的開頭 +- `'last'` - 未定義的值將被推到列表的末尾 +- `false` - 未定義的值將被視為相等,並需要由下一個欄位篩選器或原始索引排序(視情況而定) +- `-1` - 未定義的值將以較高優先級排序(升序)(如果是升序,未定義的值將出現在列表的開頭) +- `1` - 未定義的值將以較低優先級排序(降序)(如果是升序,未定義的值將出現在列表的末尾) + +> 注意:`'first'` 和 `'last'` 選項在 v8.16.0 中新增 + +```jsx +const columns = [ + { + header: () => 'Rank', + accessorKey: 'rank', + sortUndefined: -1, // 'first' | 'last' | 1 | -1 | false + }, +] +``` + +#### 排序移除 + +預設情況下,循環切換欄位排序狀態時,移除排序的功能是啟用的。您可以使用 `enableSortingRemoval` 表格選項停用此行為。此行為在您希望確保至少有一個欄位始終排序時很有用。 + +使用 `getToggleSortingHandler` 或 `toggleSorting` API 時的預設行為如下: + +`'none' -> 'desc' -> 'asc' -> 'none' -> 'desc' -> 'asc' -> ...` + +如果停用排序移除,行為將如下: + +`'none' -> 'desc' -> 'asc' -> 'desc' -> 'asc' -> ...` + +一旦欄位排序且 `enableSortingRemoval` 設為 `false`,切換該欄位的排序將永遠不會移除排序。然而,如果使用者對另一個欄位進行排序且該事件不是多重排序事件,則排序將從先前的欄位移除,僅應用於新欄位。 + +> 如果您希望確保至少有一個欄位始終排序,請將 `enableSortingRemoval` 設為 `false`。 + +```jsx +const table = useReactTable({ + columns, + data, + enableSortingRemoval: false, // 停用移除欄位排序的功能(始終為 none -> asc -> desc -> asc) +}) +``` + +#### 多重排序 + +如果使用 `column.getToggleSortingHandler` API,預設情況下啟用同時對多個欄位進行排序。如果使用者在點擊欄位標題時按住 `Shift` 鍵,表格將對該欄位以及已排序的欄位進行排序。如果您使用 `column.toggleSorting` API,則需要手動傳遞是否使用多重排序。(`column.toggleSorting(desc, multi)`)。 + +##### 停用多重排序 + +您可以使用 `enableMultiSort` 欄位選項或表格選項,停用特定欄位或整個表格的多重排序功能。停用特定欄位的多重排序將用新欄位的排序替換所有現有排序。 + +```jsx +const columns = [ + { + header: () => 'Created At', + accessorKey: 'createdAt', + enableMultiSort: false, // 排序此欄位時,始終僅按此欄位排序 + }, + //... +] +//... +const table = useReactTable({ + columns, + data, + enableMultiSort: false, // 停用整個表格的多重排序 +}) +``` + +##### 自訂多重排序觸發器 + +預設情況下,使用 `Shift` 鍵觸發多重排序。您可以使用 `isMultiSortEvent` 表格選項更改此行為。您甚至可以通過從自訂函數返回 `true` 來指定所有排序事件都應觸發多重排序。 + +```jsx +const table = useReactTable({ + columns, + data, + isMultiSortEvent: (e) => true, // 普通點擊觸發多重排序 + //或 + isMultiSortEvent: (e) => e.ctrlKey || e.shiftKey, // 同時使用 `Ctrl` 鍵觸發多重排序 +}) +``` + +##### 多重排序限制 + +預設情況下,可以同時排序的欄位數量沒有限制。您可以使用 `maxMultiSortColCount` 表格選項設定限制。 + +```jsx +const table = useReactTable({ + columns, + data, + maxMultiSortColCount: 3, // 僅允許同時排序 3 個欄位 +}) +``` + +##### 多重排序移除 + +預設情況下,移除多重排序的功能是啟用的。您可以使用 `enableMultiRemove` 表格選項停用此行為。 + +```jsx +const table = useReactTable({ + columns, + data, + enableMultiRemove: false, // 停用移除多重排序的功能 +}) +``` + +### 排序 API + +有許多與排序相關的 API 可用於連接到您的 UI 或其他邏輯。以下是所有排序 API 及其部分使用案例的清單。 + +- `table.setSorting` - 直接設定排序狀態。 +- `table.resetSorting` - 將排序狀態重置為初始狀態或清除它。 + +- `column.getCanSort` - 用於啟用/停用欄位的排序 UI。 +- `column.getIsSorted` - 用於顯示欄位的視覺排序指示器。 + +- `column.getToggleSortingHandler` - 用於連接欄位的排序 UI。添加到排序箭頭(圖示按鈕)、選單項目或整個欄位標題單元格。此處理程序將使用正確的參數調用 `column.toggleSorting`。 +- `column.toggleSorting` - 用於連接欄位的排序 UI。如果使用此選項而非 `column.getToggleSortingHandler`,則需要手動傳遞是否使用多重排序。(`column.toggleSorting(desc, multi)`) +- `column.clearSorting` - 用於特定欄位的「清除排序」按鈕或選單項目。 + +- `column.getNextSortingOrder` - 用於顯示欄位下一次排序的方向。(在工具提示/選單項目/aria-label 中顯示 asc/desc/clear) +- `column.getFirstSortDir` - 用於顯示欄位第一次排序的方向。(在工具提示/選單項目/aria-label 中顯示 asc/desc) +- `column.getAutoSortDir` - 決定欄位的第一次排序方向是升序還是降序。 +- `column.getAutoSortingFn` - 內部用於查找欄位的預設排序函數(如果未指定)。 +- `column.getSortingFn` - 返回欄位使用的確切排序函數。 + +- `column.getCanMultiSort` - 用於啟用/停用 diff --git a/docs/zh-hant/guide/tables.md b/docs/zh-hant/guide/tables.md new file mode 100644 index 0000000000..02fa587ae1 --- /dev/null +++ b/docs/zh-hant/guide/tables.md @@ -0,0 +1,102 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:40:06.545Z' +title: 表格實例 +--- +## API + +[表格 API](../api/core/table) + +## 表格實例指南 + +TanStack Table 是一個無頭 UI 函式庫。當我們談論 `table` 或「表格實例」時,並不是指實際的 `` 元素,而是指包含表格狀態和 API 的核心表格物件。`table` 實例是通過呼叫適配器的 `createTable` 函式(例如 `useReactTable`、`useVueTable`、`createSolidTable`、`createSvelteTable`、`createAngularTable`、`useQwikTable`)來建立的。 + +從 `createTable` 函式(來自框架適配器)返回的 `table` 實例是你將與之互動的主要物件,用於讀取和變更表格狀態。這是 TanStack Table 中一切發生的核心位置。當你開始渲染 UI 時,將會使用此 `table` 實例的 API。 + +### 建立表格實例 + +建立表格實例需要 3 個必要的 `options`:`columns`、`data` 和 `getCoreRowModel` 的實作。雖然還有數十個其他表格選項可用於配置功能和行為,但這 3 個是必需的。 + +#### 定義資料 + +將資料定義為具有穩定參考的物件陣列。`data` 可以來自任何地方,例如 API 回應或靜態定義在程式碼中,但必須具有穩定參考以防止無限重新渲染。如果使用 TypeScript,你為資料指定的類型將作為 `TData` 泛型使用。更多資訊請參閱[資料指南](../guide/data)。 + +#### 定義欄位 + +欄位定義在前一節的[欄位定義指南](../guide/column-defs)中有詳細說明。不過我們在此提醒,當你定義欄位的類型時,應使用與資料相同的 `TData` 類型。 + +```ts +const columns: ColumnDef[] = [] //將 User 類型作為泛型 TData 類型傳遞 +//或 +const columnHelper = createColumnHelper() //將 User 類型作為泛型 TData 類型傳遞 +``` + +欄位定義是我們告訴 TanStack Table 每個欄位應如何透過 `accessorKey` 或 `accessorFn` 存取和/或轉換行資料的地方。更多資訊請參閱[欄位定義指南](../guide/column-defs#creating-accessor-columns)。 + +#### 傳入行模型 + +這在[行模型指南](../guide/row-models)中有更詳細的說明,但現在只需從 TanStack Table 導入 `getCoreRowModel` 函式並將其作為表格選項傳入即可。根據你計劃使用的功能,後續可能需要傳入其他行模型。 + +```ts +import { getCoreRowModel } from '@tanstack/[framework]-table' + +const table = createTable({ columns, data, getCoreRowModel: getCoreRowModel() }) +``` + +#### 初始化表格實例 + +定義好 `columns`、`data` 和 `getCoreRowModel` 後,我們現在可以建立基本的表格實例,並傳入任何其他需要的表格選項。 + +```ts +//vanilla js +const table = createTable({ columns, data, getCoreRowModel: getCoreRowModel() }) + +//angular +this.table = createAngularTable({ columns: this.columns, data: this.data(), getCoreRowModel: getCoreRowModel() }) + +//lit +const table = this.tableController.table({ columns, data, getCoreRowModel: getCoreRowModel() }) + +//qwik +const table = useQwikTable({ columns, data, getCoreRowModel: getCoreRowModel() }) + +//react +const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel() }) + +//solid +const table = createSolidTable({ columns, get data() { return data() }, getCoreRowModel: getCoreRowModel() }) + +//svelte +const table = createSvelteTable({ columns, data, getCoreRowModel: getCoreRowModel() }) + +//vue +const table = useVueTable({ columns, data, getCoreRowModel: getCoreRowModel() }) +``` + +那麼 `table` 實例中包含了什麼?讓我們看看可以與表格實例進行哪些互動。 + +### 表格狀態 + +表格實例包含所有表格狀態,可透過 `table.getState()` API 存取。每個表格功能會在表格狀態中註冊各種狀態。例如,行選擇功能會註冊 `rowSelection` 狀態,分頁功能會註冊 `pagination` 狀態等。 + +每個功能還會在表格實例上有對應的狀態設定 API 和狀態重置 API。例如,行選擇功能會有 `setRowSelection` API 和 `resetRowSelection`。 + +```ts +table.getState().rowSelection //讀取行選擇狀態 +table.setRowSelection((old) => ({...old})) //設定行選擇狀態 +table.resetRowSelection() //重置行選擇狀態 +``` + +這在[表格狀態指南](../framework/react/guide/table-state)中有更詳細的說明。 + +### 表格 API + +每個功能會建立數十個表格 API,幫助你以不同方式讀取或變更表格狀態。 + +核心表格實例和所有其他功能 API 的參考文件可以在 API 文件中找到。 + +例如,你可以在這裡找到核心表格實例的 API 文件:[表格 API](../api/core/table#table-api) + +### 表格行模型 + +有一組特殊的表格實例 API 用於從表格實例中讀取行,稱為行模型。TanStack Table 具有進階功能,生成的資料行可能與你最初傳入的 `data` 陣列有很大不同。要了解更多關於可以作為表格選項傳入的不同行模型,請參閱[行模型指南](../guide/row-models)。 diff --git a/docs/zh-hant/guide/virtualization.md b/docs/zh-hant/guide/virtualization.md new file mode 100644 index 0000000000..f5bea55f81 --- /dev/null +++ b/docs/zh-hant/guide/virtualization.md @@ -0,0 +1,21 @@ +--- +source-updated-at: '2025-03-20T21:15:29.000Z' +translation-updated-at: '2025-05-08T23:39:28.469Z' +title: 虛擬化 +--- +## 範例 + +想直接查看實作方式嗎?請參考以下範例: + +- [virtualized-columns](../framework/react/examples/virtualized-columns) +- [virtualized-rows (動態行高)](../framework/react/examples/virtualized-rows) +- [virtualized-rows (固定行高)](../../../../virtual/v3/docs/framework/react/examples/table) +- [virtualized-infinite-scrolling](../framework/react/examples/virtualized-infinite-scrolling) + +## API + +[TanStack Virtual Virtualizer API](../../../../virtual/v3/docs/api/virtualizer) + +## 虛擬化指南 (Virtualization Guide) + +TanStack Table 套件本身並未內建任何虛擬化 (virtualization) API 或功能,但可以輕鬆與其他虛擬化函式庫搭配使用,例如 [react-window](https://www.npmjs.com/package/react-window) 或 TanStack 自家的 [TanStack Virtual](https://tanstack.com/virtual/v3)。本指南將展示一些將 TanStack Table 與 TanStack Virtual 結合使用的策略。 diff --git a/docs/zh-hant/installation.md b/docs/zh-hant/installation.md new file mode 100644 index 0000000000..f80f3dd263 --- /dev/null +++ b/docs/zh-hant/installation.md @@ -0,0 +1,82 @@ +--- +source-updated-at: '2024-05-19T21:37:34.000Z' +translation-updated-at: '2025-05-08T23:39:46.300Z' +title: 安裝 +--- +在深入探討 API 之前,先來完成安裝設定! + +使用你喜愛的 npm 套件管理工具安裝表格適配器 (adapter) 作為相依套件。 + +_只需安裝以下其中一個套件:_ + +## React Table + +```bash +npm install @tanstack/react-table +``` + +`@tanstack/react-table` 套件相容於 React 16.8、React 17、React 18 及 React 19。 + +> 注意:雖然 React 適配器 (adapter) 可與 React 19 搭配使用,但可能無法相容於即將隨 React 19 推出的新 React 編譯器 (React Compiler)。此問題可能於未來的 TanStack Table 更新中修正。 + +## Vue Table + +```bash +npm install @tanstack/vue-table +``` + +`@tanstack/vue-table` 套件相容於 Vue 3。 + +## Solid Table + +```bash +npm install @tanstack/solid-table +``` + +`@tanstack/solid-table` 套件相容於 Solid-JS 1。 + +## Svelte Table + +```bash +npm install @tanstack/svelte-table +``` + +`@tanstack/svelte-table` 套件相容於 Svelte 3 及 Svelte 4。 + +> 注意:目前尚未內建 Svelte 5 適配器 (adapter),但你仍可透過安裝 `@tanstack/table-core` 套件並使用社群提供的自訂適配器 (custom adapter) 來搭配 Svelte 5 使用。可參考此 [PR](https://github.com/TanStack/table/pull/5403) 獲取靈感。 + +## Qwik Table + +```bash +npm install @tanstack/qwik-table +``` + +`@tanstack/qwik-table` 套件相容於 Qwik 1。 + +> 注意:近期將發布支援 Qwik 2 的「重大變更 (breaking change)」版本。此更新將以次要版本號 (minor version) 遞增方式發布,並會提供相關文件說明。Qwik 2 本身並無重大變更,但其在 npm 註冊表上的名稱將變更,且需搭配不同的同儕相依套件 (peer dependencies)。 + +> 注意:目前的 Qwik 適配器 (adapter) 僅支援 CSR。更多改進可能需等待未來的表格版本。 + +## Angular Table + +```bash +npm install @tanstack/angular-table +``` + +`@tanstack/angular-table` 套件相容於 Angular 17。此 Angular 適配器 (adapter) 採用新的 Angular 訊號 (Signal) 實作方式。 + +## Lit Table + +```bash +npm install @tanstack/lit-table +``` + +`@tanstack/lit-table` 套件相容於 Lit 3。 + +## Table Core (無框架版本) + +```bash +npm install @tanstack/table-core +``` + +找不到你喜愛的框架(或特定框架版本)嗎?你隨時可以直接使用 `@tanstack/table-core` 套件,並在自己的程式碼庫中建置專屬適配器 (adapter)。通常只需一層薄薄的封裝 (thin wrapper) 來管理特定框架的狀態與渲染。可瀏覽所有其他適配器的[原始碼](https://github.com/TanStack/table/tree/main/packages)了解其運作方式。 diff --git a/docs/zh-hant/introduction.md b/docs/zh-hant/introduction.md new file mode 100644 index 0000000000..38955e77c4 --- /dev/null +++ b/docs/zh-hant/introduction.md @@ -0,0 +1,70 @@ +--- +source-updated-at: '2024-03-22T01:02:38.000Z' +translation-updated-at: '2025-05-08T23:39:51.959Z' +title: 簡介 +--- +TanStack Table 是一個**無頭 UI (Headless UI)** 函式庫,用於為 TS/JS、React、Vue、Solid、Qwik 和 Svelte 構建強大的表格與資料網格。 + +## 什麼是「無頭 UI (Headless UI)」? + +**無頭 UI (Headless UI)** 是指那些提供 UI 元素與互動邏輯、狀態、處理和 API,但**不提供標記、樣式或預建置實作**的函式庫與工具。還不太明白嗎?😉 無頭 UI 有幾個主要目標: + +構建複雜 UI 最困難的部分通常圍繞著狀態、事件、副作用、資料計算/管理。透過將這些關注點從標記、樣式和實作細節中分離出來,我們的邏輯和元件可以更加模組化且可重複使用。 + +構建 UI 是一個非常品牌化和客製化的過程,即使這意味著選擇一個設計系統或遵循設計規範。為了支援這種客製化體驗,基於元件的 UI 函式庫需要圍繞標記和樣式自訂提供龐大(且看似無窮無盡)的 API 表面。無頭 UI 函式庫將你的邏輯與 UI 解耦。 + +當你使用無頭 UI 函式庫時,**資料處理、狀態管理和業務邏輯**這些複雜任務會由函式庫處理,讓你專注於因應不同實作和使用案例而異的高基數決策。 + +> 想深入了解?[閱讀更多關於無頭 UI (Headless UI)](https://www.merrickchristensen.com/articles/headless-user-interface-components/)。 + +## 基於元件的函式庫 vs 無頭函式庫 + +在表格/資料網格函式庫的生態系統中,主要有兩大類別: + +- 基於元件的表格函式庫 +- 無頭表格函式庫 + +### 我該使用哪種表格函式庫? + +每種方法都有微妙的權衡。了解這些細微差別將幫助你為應用程式和團隊做出正確的決策。 + +### 基於元件的表格函式庫 + +基於元件的表格函式庫通常會提供功能豐富的即用解決方案和現成的元件/標記,並附帶樣式/主題。[AG Grid](https://ag-grid.com/react-data-grid/?utm_source=reacttable&utm_campaign=githubreacttable) 是這類表格函式庫的絕佳範例。 + +**優點:** + +- 提供現成的標記/樣式 +- 幾乎無需設置 +- 開箱即用的體驗 + +**缺點:** + +- 對標記的控制較少 +- 自訂樣式通常基於主題 +- 較大的套件體積 +- 高度依賴框架轉接器和平台 + +**如果你想要一個現成的表格,且設計/套件體積不是硬性要求**,那麼你應該考慮使用基於元件的表格函式庫。 + +市面上有許多基於元件的表格函式庫,但我們認為 [AG Grid](https://ag-grid.com/react-data-grid/?utm_source=reacttable&utm_campaign=githubreacttable) 是黃金標準,也是我們最喜歡的網格兄弟(別告訴其他人 🤫)。 + +### 無頭表格函式庫 + +無頭表格函式庫通常會提供函式、狀態、工具和事件監聽器,讓你構建自己的表格標記或附加到現有的表格標記上。 + +**優點:** + +- 完全控制標記和樣式 +- 支援所有樣式模式(CSS、CSS-in-JS、UI 函式庫等) +- 較小的套件體積 +- 可攜性。能在任何執行 JS 的地方運行! + +**缺點:** + +- 需要更多設置 +- 不提供標記、樣式或主題 + +**如果你想要一個更輕量的表格或對設計有完全控制權**,那麼你應該考慮使用無頭表格函式庫。 + +市面上很少有無頭表格函式庫,顯然,**TanStack Table** 是我們的最愛! diff --git a/docs/zh-hant/overview.md b/docs/zh-hant/overview.md new file mode 100644 index 0000000000..5c65904aa9 --- /dev/null +++ b/docs/zh-hant/overview.md @@ -0,0 +1,64 @@ +--- +source-updated-at: '2024-05-12T19:19:51.000Z' +translation-updated-at: '2025-05-08T23:40:12.981Z' +title: 概述 +--- +TanStack Table 的核心是 **框架無關 (framework agnostic)**,這意味著無論你使用哪種框架,其 API 都保持一致。根據你所使用的框架,我們提供了適配器 (adapters) 來簡化與表格核心的互動。請參閱「Adapters」選單以查看可用的適配器。 + +## TypeScript + +雖然 TanStack Table 是用 [TypeScript](https://www.typescriptlang.org/) 編寫的,但在你的應用程式中使用 TypeScript 是可選的(但強烈推薦,因為它能為你和程式碼庫帶來顯著的好處)。 + +如果你使用 TypeScript,你將獲得頂級的類型安全性和編輯器自動補全功能,適用於所有表格 API 和狀態。 + +## 無頭式 (Headless) + +如 [介紹](../introduction) 部分所述,TanStack Table 是 **無頭式 (headless)** 的。這意味著它不會渲染任何 DOM 元素,而是依賴於你(UI/UX 開發者)來提供表格的標記和樣式。這是一種極佳的方式,可以構建適用於任何 UI 框架的表格,包括 React、Vue、Solid、Svelte、Qwik、Angular,甚至是 JS-to-native 平台如 React Native! + +## 無關性 (Agnostic) + +由於 TanStack Table 是無頭式的,並且運行在純 JavaScript 核心上,它在以下幾個方面具有無關性: + +1. TanStack Table 是 **框架無關 (Framework Agnostic)** 的,這意味著你可以將其與任何你想要的 JavaScript 框架(或函式庫)一起使用。TanStack Table 預設提供了適用於 React、Vue、Solid、Svelte 和 Qwik 的即用型適配器,但如果你需要,也可以創建自己的適配器。 +2. TanStack Table 是 **CSS / 元件函式庫無關 (CSS / Component Library Agnostic)** 的,這意味著你可以將 TanStack Table 與任何 CSS 策略或元件函式庫一起使用。TanStack Table 本身不會渲染任何表格標記或樣式。這些都由你來提供!想使用 Tailwind 或 ShadCN?沒問題!想使用 Material UI 或 Bootstrap?也沒問題!有自己的自訂設計系統?TanStack Table 正是為你而設計的! + +## 核心物件與類型 + +表格核心使用以下抽象概念,通常由適配器公開: + +- [資料 (Data)](../guide/data) - 你提供給表格的核心資料陣列 +- [欄位定義 (Column Defs)](../guide/column-defs):用於配置欄位及其資料模型、顯示模板等的物件 +- [表格實例 (Table Instance)](../guide/tables):包含狀態和 API 的核心表格物件 +- [列模型 (Row Models)](../guide/row-models):根據你使用的功能,將 `data` 陣列轉換為有用的列的方式 +- [列 (Rows)](../guide/rows):每一列都對應其相應的資料列,並提供列專用的 API +- [儲存格 (Cells)](../guide/cells):每個儲存格對應其相應的列-欄位交集,並提供儲存格專用的 API +- [標題群組 (Header Groups)](../guide/header-groups):標題群組是嵌套標題層級的計算切片,每個群組包含一組標題 +- [標題 (Headers)](../guide/headers):每個標題直接關聯或衍生自其欄位定義,並提供標題專用的 API +- [欄位 (Columns)](../guide/columns):每個欄位對應其相應的欄位定義,並提供欄位專用的 API + +## 功能 + +TanStack Table 可以幫助你構建幾乎任何你能想像的表格類型。它內建了以下功能的狀態和 API: + +- [欄位分面 (Column Faceting)](../guide/column-faceting) - 列出欄位的唯一值列表或欄位的最小/最大值 +- [欄位過濾 (Column Filtering)](../guide/column-filtering) - 根據欄位的搜尋值過濾列 +- [欄位分組 (Column Grouping)](../guide/grouping) - 將欄位分組、執行聚合等 +- [欄位排序 (Column Ordering)](../guide/column-ordering) - 動態變更欄位順序 +- [欄位固定 (Column Pinning)](../guide/column-pinning) - 將欄位固定(凍結)在表格的左側或右側 +- [欄位調整大小 (Column Sizing)](../guide/column-sizing) - 動態調整欄位大小(欄位調整手柄) +- [欄位可見性 (Column Visibility)](../guide/column-visibility) - 顯示/隱藏欄位 +- [全域分面 (Global Faceting)](../guide/global-faceting) - 列出整個表格的唯一值列表或最小/最大值 +- [全域過濾 (Global Filtering)](../guide/global-filtering) - 根據整個表格的搜尋值過濾列 +- [列展開 (Row Expanding)](../guide/expanding) - 展開/折疊列(子列) +- [列分頁 (Row Pagination)](../guide/pagination) - 對列進行分頁 +- [列固定 (Row Pinning)](../guide/row-pinning) - 將列固定(凍結)在表格的頂部或底部 +- [列選擇 (Row Selection)](../guide/row-selection) - 選擇/取消選擇列(複選框) +- [列排序 (Row Sorting)](../guide/sorting) - 根據欄位值對列進行排序 + +這些只是你可以用 TanStack Table 構建的部分功能。還有許多其他功能可以與內建功能一起實現。 + +[虛擬化 (Virtualization)](../guide/virtualization) 是一個未內建於 TanStack Table 的功能示例,但可以通過使用其他函式庫(如 [TanStack Virtual](https://tanstack.com/virtual/v3))並將其與其他表格渲染邏輯結合來實現。 + +TanStack Table 還支援 [自訂功能 (Custom Features)](../guide/custom-features)(插件),你可以使用這些功能來修改表格實例,以更整合的方式為表格添加自訂邏輯。 + +當然,你也可以直接編寫自己的狀態和鉤子 (hooks) 來為表格添加任何其他功能。TanStack Table 核心的功能只是一個堅實的基礎,重點關注性能和開發者體驗 (DX)。 diff --git a/docs/zh-hant/vanilla.md b/docs/zh-hant/vanilla.md new file mode 100644 index 0000000000..2c3472bef3 --- /dev/null +++ b/docs/zh-hant/vanilla.md @@ -0,0 +1,16 @@ +--- +source-updated-at: '2024-01-24T21:39:34.000Z' +translation-updated-at: '2025-05-08T23:39:23.339Z' +title: Vanilla JS (無框架) +--- +`@tanstack/table-core` 函式庫包含了 TanStack Table 的核心邏輯。如果您使用的是非標準框架或無法使用任何框架,可以直接透過 TypeScript 或 JavaScript 使用核心函式庫。 + +## `createTable` + +接收一個 `options` 物件並回傳一個表格。 + +```tsx +import { createTable } from '@tanstack/table-core' + +const table = createTable(options) +```