import { VNode } from 'vue'; import { computed, defineComponent } from '@vue/composition-api'; import { useStoreInject } from '@/lib/store'; import { Rower } from '@/lib/components/body/row/rower'; import { BODY_ROW } from '@/lib/constants/dom-role'; import { fixStyle } from '@/lib/utils/dom'; import { props } from '@/lib/components/body/group/props'; import { log } from '@/lib/utils/log'; import { BODY_ROW_TREE_LEVEL } from '@/lib/constants/dom-class'; export const RowsGrouper = defineComponent({ name: 'GridableGrouper', props, emits: ['contextmenu'], setup() { const store = useStoreInject(); // const lruForRow = createLRU(30); return { // lruForRow, data2DRecord: computed(() => store.state.index.data2D), rowRecord: computed(() => store.state.view.rowRecord), activeStatus: computed(() => store.state.activeStatus), }; }, render(h) { log('[render][group]'); const { rowRecord, data2DRecord, activeRowIds, columns, width, pin, selectionArea, calculatingArea, clickedCell, dbClickedCell, } = this; // 当滚动引起的渲染可以使用 cache const getClickedColumnId = (rowId: string) => { if (rowId === clickedCell?.rowId) { return clickedCell.columnId; } return ''; }; const getDBClickedColumnId = (rowId: string) => { if (rowId === dbClickedCell?.rowId) { return dbClickedCell.columnId; } return ''; }; const getSelectionProp = (rowIndex: number) => { if (selectionArea?.row?.length !== 2) { return {}; } const [start, end] = selectionArea.row; if (start <= rowIndex && rowIndex <= end) { return { selectedColumnIndexRange: selectionArea.column, isSelectedTopEdge: rowIndex === start, isSelectedBottomEdge: rowIndex === end, selectedLink: selectionArea.link, }; } return {}; }; const getCalculatingProp = (rowIndex: number) => { if (calculatingArea?.row?.length !== 2) { return {}; } const [start, end] = calculatingArea.row; if (start <= rowIndex && rowIndex <= end) { return { calculatingColumnIndexRange: calculatingArea.column, isCalculatingTopEdge: rowIndex === start, isCalculatingBottomEdge: rowIndex === end, }; } return {}; }; const renderRowerLocation = ( key: string, index: number, top: number, height: number, width: number, treeLevel: number, rower: VNode, ) => { return h( 'div', { key, attrs: { role: BODY_ROW, }, class: { 'grid-row': true, 'row-odd': index % 2, [`${BODY_ROW_TREE_LEVEL}_${treeLevel}`]: true, }, style: fixStyle({ transform: top, height, width, }), }, [rower], ); }; const renderRower = ( key: string, index: number, rowId: string, hasChildren: boolean, isExpand: boolean, treePath: string[], ) => { return h(Rower, { key, props: { pin, id: rowId, index, columns, data: data2DRecord[rowId], treeHasChildren: hasChildren, treeExpand: isExpand, treePath, clickedColumnId: getClickedColumnId(rowId), dbClickedColumnId: getDBClickedColumnId(rowId), ...getSelectionProp(index), ...getCalculatingProp(index), }, }); }; const rowsTimeS = performance.now(); const rows = activeRowIds.reduce((acc, id: string) => { const currentRowRecord = rowRecord[id]; if (currentRowRecord) { const key = `${pin}_${id}`; const index = currentRowRecord.index; const top = currentRowRecord.top; const height = currentRowRecord.height; const treeExpand = currentRowRecord.expand; const treeHasChildren = currentRowRecord.hasChildren; const treePath = currentRowRecord.treePath; acc.push( renderRowerLocation( key, index, top, height, width, treePath?.length || 0, renderRower(key, index, id, treeHasChildren, treeExpand, treePath), ), ); } return acc; }, []); log('[cost][rowsTimeS]', performance.now() - rowsTimeS); return h( 'div', { class: { 'header-group-inner': true, }, }, [rows], ); }, });