/** * 对应表头的一格 */ import React, { createContext, useCallback, useMemo, useRef } from 'react' import { HeaderProps } from 'react-table' import cns from 'classnames' import { concat } from '../utils' import SortIcon from './SortIcon' import FilterIcon from './filter/FilterIcon' import { useReportWidth } from './hooks' import { useColumnWidths } from './providers/ColumnWidthsProvider' import { useTable } from './providers/TableProvider' import { useScrollbarWidth } from './providers/ScrollbarWidthProvider' import { getFixedStyle } from './utils' import { useHorizontalScroll } from './providers/HorizontalScrollProvider' export type Props = HeaderProps & { isLast: boolean index: number className?: string } export default function Header(props: Props) { const { column, isLast = false, index: columnIndex, columns, className } = props const { prefix: tablePrefix, fixHead } = useTable() const { pinnedLeft, pinnedRight } = useHorizontalScroll() const { reportHeadCellWidth, colWidths } = useColumnWidths() const { width: scrollbarWidth } = useScrollbarWidth() const ref = useRef(null) const headerPrefix = concat(tablePrefix, 'header') const thPrefix = concat(headerPrefix, 'th') const headerProps = column.getHeaderProps({ className: thPrefix }) const sortOptions = column.meta.sort const filterOptions = column.meta.filter const title = column.meta.title const sortIconView = sortOptions != null && ( ) const filterIconView = filterOptions != null && ( ) useReportWidth(ref, useCallback(nextWidth => { // Table 被隐藏后 nextWidth 会是 0 // 这种情况不处理,防止抖动 if (nextWidth === 0) return reportHeadCellWidth( column.id, fixHead && isLast // 如果是 fixHead 的最后一列,Colgroup 计算的宽度信息里会增加 scrollbarWidth // 所以这里需要去掉才是真实宽度 // 如果大于必然大于滚动条的宽度,如果有大于零但是小于滚动条的宽度再处理 ? nextWidth - scrollbarWidth : nextWidth ) }, [column.id, fixHead, isLast, reportHeadCellWidth, scrollbarWidth])) const fixedStyle = useMemo( () => getFixedStyle(colWidths, columnIndex, columns, column.meta.fixed), [colWidths, column.meta.fixed, columnIndex, columns] ) const isLeftLast = column.meta.fixed === 'left' && pinnedLeft === columnIndex const isRightFirst = column.meta.fixed === 'right' && pinnedRight === columnIndex return ( {title} {sortIconView} {filterIconView} ) } export type HeaderContext = { headerElement: HTMLDivElement | null headerPrefix: string } export const HeaderContext = createContext({ headerElement: null, headerPrefix: '' })