注意:本指南介绍的是为表格设置列定义,而非表格实例中实际生成的 column 对象。
列定义是构建表格最重要的部分,它们负责:
以下列定义"类型"并非实际的 TypeScript 类型,而是用于描述列定义的整体分类方式:
虽然列定义本质上只是普通对象,但表格核心提供了 createColumnHelper 函数,当传入行类型调用时,会返回一个工具函数,用于以最高类型安全性创建不同类型的列定义。
以下是创建和使用列辅助工具的示例:
// 定义行数据结构
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}
const columnHelper = createColumnHelper<Person>()
// 创建列!
const defaultColumns = [
// 展示列
columnHelper.display({
id: 'actions',
cell: props => <RowActions row={props.row} />,
}),
// 分组列
columnHelper.group({
header: '姓名',
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: () => <span>姓氏</span>,
footer: props => props.column.id,
}),
],
}),
// 分组列
columnHelper.group({
header: '信息',
footer: props => props.column.id,
columns: [
// 访问器列
columnHelper.accessor('age', {
header: () => '年龄',
footer: props => props.column.id,
}),
// 分组列
columnHelper.group({
header: '更多信息',
columns: [
// 访问器列
columnHelper.accessor('visits', {
header: () => <span>访问次数</span>,
footer: props => props.column.id,
}),
// 访问器列
columnHelper.accessor('status', {
header: '状态',
footer: props => props.column.id,
}),
// 访问器列
columnHelper.accessor('progress', {
header: '资料进度',
footer: props => props.column.id,
}),
],
}),
],
}),
]
// 定义行数据结构
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}
const columnHelper = createColumnHelper<Person>()
// 创建列!
const defaultColumns = [
// 展示列
columnHelper.display({
id: 'actions',
cell: props => <RowActions row={props.row} />,
}),
// 分组列
columnHelper.group({
header: '姓名',
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: () => <span>姓氏</span>,
footer: props => props.column.id,
}),
],
}),
// 分组列
columnHelper.group({
header: '信息',
footer: props => props.column.id,
columns: [
// 访问器列
columnHelper.accessor('age', {
header: () => '年龄',
footer: props => props.column.id,
}),
// 分组列
columnHelper.group({
header: '更多信息',
columns: [
// 访问器列
columnHelper.accessor('visits', {
header: () => <span>访问次数</span>,
footer: props => props.column.id,
}),
// 访问器列
columnHelper.accessor('status', {
header: '状态',
footer: props => props.column.id,
}),
// 访问器列
columnHelper.accessor('progress', {
header: '资料进度',
footer: props => props.column.id,
}),
],
}),
],
}),
]
数据列的特殊之处在于必须配置为从 data 数组中的每个项提取原始值。
有三种实现方式:
如果每个项是具有以下结构的对象:
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}
可以这样提取 firstName 值:
columnHelper.accessor('firstName')
// 或
{
accessorKey: 'firstName',
}
columnHelper.accessor('firstName')
// 或
{
accessorKey: 'firstName',
}
如果每个项是具有以下结构的对象:
type Person = {
name: {
first: string
last: string
}
info: {
age: number
visits: number
}
}
type Person = {
name: {
first: string
last: string
}
info: {
age: number
visits: number
}
}
可以这样提取 first 值:
columnHelper.accessor('name.first', {
id: 'firstName',
})
// 或
{
accessorKey: 'name.first',
id: 'firstName',
}
columnHelper.accessor('name.first', {
id: 'firstName',
})
// 或
{
accessorKey: 'name.first',
id: 'firstName',
}
如果每个项是具有以下结构的数组:
type Sales = [Date, number]
type Sales = [Date, number]
可以这样提取 number 值:
columnHelper.accessor(1)
// 或
{
accessorKey: 1,
}
columnHelper.accessor(1)
// 或
{
accessorKey: 1,
}
如果每个项是具有以下结构的对象:
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}
可以这样提取计算得到的全名值:
columnHelper.accessor(row => `${row.firstName} ${row.lastName}`, {
id: 'fullName',
})
// 或
{
id: 'fullName',
accessorFn: row => `${row.firstName} ${row.lastName}`,
}
columnHelper.accessor(row => `${row.firstName} ${row.lastName}`, {
id: 'fullName',
})
// 或
{
id: 'fullName',
accessorFn: row => `${row.firstName} ${row.lastName}`,
}
🧠 记住,访问的值将用于排序、筛选等操作,因此需要确保访问器函数返回的原始值能以有意义的方式操作。如果返回非原始值(如对象或数组),则需要提供相应的筛选/排序/分组函数来操作它们,甚至可能需要自定义这些函数!😬
列通过以下三种策略进行唯一标识:
🧠 简单记忆方法:如果使用访问器函数定义列,请提供字符串表头或唯一的 id 属性。
默认情况下,列单元格会将其数据模型值显示为字符串。可以通过提供自定义渲染实现来覆盖此行为。每个实现都会获得有关单元格、表头或表尾的相关信息,并返回框架适配器可以渲染的内容,例如 JSX/组件/字符串等。具体取决于使用的适配器。
有几种格式化器可供使用:
可以通过向 cell 属性传递函数并使用 props.getValue() 函数访问单元格值来提供自定义单元格格式化器:
columnHelper.accessor('firstName', {
cell: props => <span>{props.getValue().toUpperCase()}</span>,
})
columnHelper.accessor('firstName', {
cell: props => <span>{props.getValue().toUpperCase()}</span>,
})
单元格格式化器还可以获取 row 和 table 对象,允许超越单元格值进行更灵活的格式化。以下示例虽然使用 firstName 作为访问器,但同时显示位于原始行对象上的带前缀用户 ID:
columnHelper.accessor('firstName', {
cell: props => (
<span>{`${props.row.original.id} - ${props.getValue()}`}</span>
),
})
columnHelper.accessor('firstName', {
cell: props => (
<span>{`${props.row.original.id} - ${props.getValue()}`}</span>
),
})
有关聚合单元格的更多信息,请参阅 分组 (grouping)。
表头和表尾无法访问行数据,但仍使用相同的概念来显示自定义内容。
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.