【详解ProTable源码】高级筛选栏如何实现一行五列
实现方式
<ProTablerowKey='id'search={{span: 5,defaultFormItemsNumber: 4,submitterColSpanProps: {// @ts-ignorespan: 'auto',flex: '20',},
/>
源码解析
https://github.com/ant-design/pro-components/blob/master/packages/form/src/layouts/QueryFilter/index.tsx
spanSize
spanSize
决定了每行可容纳的表单项个数。
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
类型。 每个数组包含三项:
a. 对应断点的最大宽度(如xs
,sm
,md
等对应的宽度)。
b. 每个表单项的 span 宽度,计算方式是24 / span[key]
,这里24
是栅格系统的总列数。
c. 布局方式,默认为'horizontal'
。 -
如果未传入
span
,使用默认断点配置。
找到当前width
落在哪个断点区间,加了16是考虑row的-8px
margin的两侧padding。
- 如果找不到断点(例如宽度特别大或异常),默认使用
span = 8
和layout = 'horizontal'
- 否则使用找到的断点的配置值
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
用于控制默认展示几个表单项,避免换行。
const showLength = useMemo(() => {if (defaultFormItemsNumber !== undefined) {return defaultFormItemsNumber;}if (defaultColsNumber !== undefined) {// 折叠为一行,需要处理多行的情况请使用 defaultFormItemsNumberconst 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
进行隐藏
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 ||// 如果 超过显示长度 且 总长度超过了 24totalSize > 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'
的影响
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,
]);
代码解析
search={{span: 5,defaultFormItemsNumber: 4,submitterColSpanProps: {// @ts-ignorespan: 'auto',flex: '20',}
}}
由于有span: 5,
则spanSize
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
,不会换行展示。