实现方式
typescript
<ProTable
rowKey='id'
search={{
span: 5,
defaultFormItemsNumber: 4,
submitterColSpanProps: {
// @ts-ignore
span: 'auto',
flex: '20',
},
/>
源码解析
spanSize
spanSize 决定了每行可容纳的表单项个数。
typescript
const spanSize = useMemo(
() => getSpanConfig(layout, width + 16, span),
[layout, width, span],
);
getSpanConfig
getSpanConfig返回一个对象,包含span、layout属性。
- 如果传入的
span是一个具体数字,就直接返回这个值,不需要做响应式适配。 - 如果传入的
span是一个响应式对象(例如span = { sm: 3, md: 2 }),生成spanConfig。
spanConfig 是一个二维数组, 其中每个元素可以是 string 或 number 类型。每个数组包含三项:
1.1 对应断点的最大宽度(如 xs, sm, md 等对应的宽度)。
1.2 每个表单项的 span 宽度,计算方式是 24 / span[key],这里 24 是栅格系统的总列数。
1.3 布局方式,默认为 'horizontal'。
- 如果未传入
span,使用默认断点配置。
找到当前width落在哪个断点区间,加了16是考虑row的-8pxmargin的两侧padding。
- 如果找不到断点(例如宽度特别大或异常),默认使用
span = 8和layout = 'horizontal' - 否则使用找到的断点的配置值
typescript
const getSpanConfig = (
layout: FormProps['layout'],
width: number,
span?: SpanConfig,
): { span: number; layout: FormProps['layout'] } => {
if (span && typeof span === 'number') {
return {
span,
layout,
};
}
const spanConfig: (string | number)[][] = span
? ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].map((key) => [
CONFIG_SPAN_BREAKPOINTS[key as 'xs'],
24 / (span as any)[key as 'sm'],
'horizontal',
])
: BREAKPOINTS[(layout as 'default') || 'default'];
const breakPoint = (spanConfig || BREAKPOINTS.default).find(
(item) => width < (item[0] as number) + 16, // 16 = 2 * (ant-row -8px margin)
);
if (!breakPoint) {
return {
span: 8,
layout: 'horizontal',
};
}
return {
span: 24 / (breakPoint[1] as number),
layout: breakPoint?.[2] as 'horizontal',
};
};
showLength
用于控制默认展示几个表单项,避免换行。
typescript
const showLength = useMemo(() => {
if (defaultFormItemsNumber !== undefined) {
return defaultFormItemsNumber;
}
if (defaultColsNumber !== undefined) {
// 折叠为一行,需要处理多行的情况请使用 defaultFormItemsNumber
const oneRowControlsNumber = 24 / spanSize.span - 1;
return defaultColsNumber > oneRowControlsNumber
? oneRowControlsNumber
: defaultColsNumber;
}
return Math.max(1, 24 / spanSize.span - 1);
}, [defaultColsNumber, defaultFormItemsNumber, spanSize.span]);
defaultFormItemsNumber代表默认展示几个表单项,span是配置列数,一般而言是 8 的倍数。
- 当
defaultFormItemsNumber存在时,以defaultFormItemsNumber的值为主 - 当
defaultColsNumber存在时,会根据spanSize.span获得一行能放几个表单项oneRowControlsNumber,即const oneRowControlsNumber = 24 / spanSize.span - 1;。当defaultColsNumber > oneRowControlsNumber时,则返回oneRowControlsNumber,否则返回defaultColsNumber - 当
defaultFormItemsNumber和defaultColsNumber都不存在时,返回Math.max(1, 24 / spanSize.span - 1)
即 "最多一行展示多少减去一个按钮",但最少保证展示一个。
processedList
processedList 用于遍历所有表单项,并根据 showLength 控制哪些需要折叠隐藏。
totalSize是用于计算当前一行的表单项数,当totalSize > showLength,则把剩下的表单项的hidden属性变为true进行隐藏
typescript
const processedList = flatMapItems(items, props.ignoreRules).map(
(
item,
index,
): { itemDom: React.ReactNode; hidden: boolean; colSpan: number } => {
// 如果 formItem 自己配置了 hidden,默认使用它自己的
const colSize = React.isValidElement < any > (item)
? (item?.props?.colSize ?? 1)
: 1;
const colSpan = Math.min(spanSize.span * (colSize || 1), 24);
// 计算总的 totalSpan 长度
totalSpan += colSpan;
// 计算总的 colSize 长度
totalSize += colSize;
// ........................................
const hidden: boolean =
(item as ReactElement<{ hidden: boolean }>)?.props?.hidden ||
// 如果收起了
(collapsed &&
(firstRowFull ||
// 如果 超过显示长度 且 总长度超过了 24
totalSize > showLength) &&
!!index);
// ........................................
return {
itemDom: item,
colSpan,
hidden: false,
};
},
);
submitterColSpanProps
按钮栏配置,控制查询/重置按钮区域的样式
submitterColSpanProps 是一个可选属性,类型为一个对象。该对象使用 Omit 泛型去除了 ColProps 中的 'span' 属性,并新增了一个 'span' 属性,类型为 number 类型。也就是说,submitterColSpanProps 对象除了 'span' 属性外,还可以包含 ColProps 中的其他所有属性。
spanSize.span也用于查询、重置按钮的span
当赋值给span的值为number类型的时候,他会给出现ant-col-number值 ant-col-offset-(24-number值)的css样式
所以在本示例中给出string类型的字符串'auto',则只会出现ant-col-auto,由于不存在这种css样式,所以会受到flex: '20'的影响
typescript
const offset = useMemo(() => {
const offsetSpan =
(currentSpan % 24) + (props.submitterColSpanProps?.span ?? spanSize.span);
if (offsetSpan > 24) {
return 24 - (props.submitterColSpanProps?.span ?? spanSize.span);
}
return 24 - offsetSpan;
}, [
currentSpan,
(currentSpan % 24) + (props.submitterColSpanProps?.span ?? spanSize.span),
props.submitterColSpanProps?.span,
]);
代码解析
typescript
search={{
span: 5,
defaultFormItemsNumber: 4,
submitterColSpanProps: {
// @ts-ignore
span: 'auto',
flex: '20',
}
}}
由于有span: 5,则spanSize
typescript
spanSize:{
span:5,
layout:'horizontal'
}
- 没有
defaultFormItemsNumber: 4只有span: 5,则showLength = 3.8,因为向下取整,才会只展示3个 - 有
defaultFormItemsNumbe: 4没有span:5,则showLength = 4。而span=8(默认),那么一行展示3个,但是由于defaultFormItemsNumber = 4,会换行展示1个,相当于两行。 - 有
defaultFormItemsNumbe: 4有span:5,则showLength = 4。而span=5,在24/5的情况下,向下取整一行展示4个,由于defaultFormItemsNumber = 4,不会换行展示。