Table State (Vue) 指南

Table State (Vue) 指南

TanStack Table 拥有一个简单的底层内部状态管理系统,用于存储和管理表格的状态。它还允许您选择性地提取任何您需要在自己的状态管理中进行管理的状态。本指南将引导您了解与表格状态交互和管理表格状态的各种方法。

访问表格状态

您无需进行任何特殊设置即可使表格状态正常工作。如果您在 stateinitialState 或任何 on[State]Change 表格选项中都不传递任何内容,表格将自行管理其内部状态。您可以通过使用 table.getState() 表格实例 API 来访问此内部状态的任何部分。

ts
const table = useVueTable({
  columns,
  data: dataRef, // Reactive data support
  //...
})

console.log(table.getState()) //access the entire internal state
console.log(table.getState().rowSelection) //access just the row selection state
const table = useVueTable({
  columns,
  data: dataRef, // Reactive data support
  //...
})

console.log(table.getState()) //access the entire internal state
console.log(table.getState().rowSelection) //access just the row selection state

使用响应式数据

v8.20.0 新增

useVueTable hook 现在支持响应式数据。这意味着您可以将包含数据的 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, // Pass the reactive data ref
})

// Later, updating dataRef will automatically update the table
dataRef.value = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 3, name: 'Doe' }
]
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, // Pass the reactive data ref
})

// Later, updating dataRef will automatically update the table
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' }
])

// This will NOT update the table ❌
dataRef.value.push({ id: 4, name: 'John' })

// This will update the table ✅
dataRef.value = [
  ...dataRef.value,
  { id: 4, name: 'John' }
]
const dataRef = ref([
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' }
])

// This will NOT update the table ❌
dataRef.value.push({ id: 4, name: 'John' })

// This will update the table ✅
dataRef.value = [
  ...dataRef.value,
  { id: 4, name: 'John' }
]

自定义初始状态

如果对于某些状态,您只需要自定义其初始默认值,那么您仍然不需要自己管理任何状态。您只需在表格实例的 initialState 选项中设置值即可。

jsx
const table = useVueTable({
  columns,
  data,
  initialState: {
    columnOrder: ['age', 'firstName', 'lastName'], //customize the initial column order
    columnVisibility: {
      id: false //hide the id column by default
    },
    expanded: true, //expand all rows by default
    sorting: [
      {
        id: 'age',
        desc: true //sort by age in descending order by default
      }
    ]
  },
  //...
})
const table = useVueTable({
  columns,
  data,
  initialState: {
    columnOrder: ['age', 'firstName', 'lastName'], //customize the initial column order
    columnVisibility: {
      id: false //hide the id column by default
    },
    expanded: true, //expand all rows by default
    sorting: [
      {
        id: 'age',
        desc: true //sort by age in descending order by default
      }
    ]
  },
  //...
})

注意:每个特定状态只需在 initialState 或 state 中指定一个,而不是两者都指定。如果您将某个特定状态值同时传递给 initialState 和 state,则 state 中的已初始化状态将覆盖 initialState 中任何相应的对应值。

受控状态

如果您需要在应用程序的其他区域轻松访问表格状态,TanStack Table 可以让您轻松地在自己的状态管理系统中控制和管理任何或所有表格状态。您可以通过将自己的状态和状态管理函数传递给 state 和 on[State]Change 表格选项来完成此操作。

独立受控状态

您可以只控制您需要轻松访问的状态。如果您不需要,则不必控制所有表格状态。建议仅根据具体情况控制所需的状态。

为了控制某个特定状态,您需要将相应的 state 值和 on[State]Change 函数都传递给表格实例。

让我们以“手动”服务器端数据获取场景中的过滤、排序和分页为例。您可以将过滤、排序和分页状态存储在自己的状态管理中,但如果您的 API 不需要这些值(如列顺序、列可见性等),则可以将其排除。

ts
const columnFilters = ref([]) //no default filters
const sorting = ref([{
  id: 'age',
  desc: true, //sort by age in descending order by default
}])
const pagination = ref({ pageIndex: 0, pageSize: 15 }

//Use our controlled state values to fetch data
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
  },
})
//...
const columnFilters = ref([]) //no default filters
const sorting = ref([{
  id: 'age',
  desc: true, //sort by age in descending order by default
}])
const pagination = ref({ pageIndex: 0, pageSize: 15 }

//Use our controlled state values to fetch data
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
//create a table instance with default state values
const table = useVueTable({
  get columns() {
    return columns.value
  },
  data,
  //... Note: `state` values are NOT passed in yet
})

const state = ref({
  ...table.initialState,
  pagination: {
    pageIndex: 0,
    pageSize: 15
  }
})
const setState = updater => {
  state.value = updater instanceof Function ? updater(state.value) : updater
}

//Use the table.setOptions API to merge our fully controlled state onto the table instance
table.setOptions(prev => ({
  ...prev, //preserve any other options that we have set up above
  get state() {
    return state.value
  },
  onStateChange: setState //any state changes will be pushed up to our own state management
}))
//create a table instance with default state values
const table = useVueTable({
  get columns() {
    return columns.value
  },
  data,
  //... Note: `state` values are NOT passed in yet
})

const state = ref({
  ...table.initialState,
  pagination: {
    pageIndex: 0,
    pageSize: 15
  }
})
const setState = updater => {
  state.value = updater instanceof Function ? updater(state.value) : updater
}

//Use the table.setOptions API to merge our fully controlled state onto the table instance
table.setOptions(prev => ({
  ...prev, //preserve any other options that we have set up above
  get state() {
    return state.value
  },
  onStateChange: setState //any state changes will be pushed up to our own state management
}))

状态变更回调

到目前为止,我们已经看到了 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 //required because we are using `onSortingChange`
    },
  },
  onSortingChange: setSorting, //makes the `state.sorting` controlled
})
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 //required because we are using `onSortingChange`
    },
  },
  onSortingChange: setSorting, //makes the `state.sorting` controlled
})

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<SortingState[]>([
  {
    id: 'age', //you should get autocomplete for the `id` and `desc` properties
    desc: true,
  }
])
import { useVueTable, type SortingState } from '@tanstack/vue-table'
//...
const sorting = ref<SortingState[]>([
  {
    id: 'age', //you should get autocomplete for the `id` and `desc` properties
    desc: true,
  }
])
我们的合作伙伴
Code Rabbit
AG Grid
订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

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

订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

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