refactor: table

pull/4639/head
tangjinzhou 2021-09-06 10:31:54 +08:00
parent 456e3ae404
commit a64ed0d623
22 changed files with 260 additions and 104 deletions

View File

@ -1,4 +1,5 @@
import { defineComponent, ExtractPropTypes, inject, nextTick } from 'vue';
import type { ExtractPropTypes } from 'vue';
import { defineComponent, inject, nextTick } from 'vue';
import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
import VcCheckbox from '../vc-checkbox';

View File

@ -9,7 +9,7 @@ import type { ValidateMessages } from '../form/interface';
import type { TransferLocale } from '../transfer';
import type { PickerLocale as DatePickerLocale } from '../date-picker/generatePicker';
import type { PaginationLocale } from '../pagination/Pagination';
import { TableLocale } from '../table/interface';
import type { TableLocale } from '../table/interface';
interface TransferLocaleForEmpty {
description: string;

View File

@ -1,5 +1,5 @@
import { defineComponent } from 'vue';
import { ColumnType } from './interface';
import type { ColumnType } from './interface';
export type ColumnProps = ColumnType;
export default defineComponent<ColumnProps>({

View File

@ -1,5 +1,5 @@
import { defineComponent } from 'vue';
import { ColumnGroupProps } from '../vc-table/sugar/ColumnGroup';
import type { ColumnGroupProps } from '../vc-table/sugar/ColumnGroup';
export default defineComponent<ColumnGroupProps<any>>({
name: 'ATableColumnGroup',

View File

@ -1,5 +1,5 @@
import classNames from '../_util/classNames';
import { TableLocale } from './interface';
import type { TableLocale } from './interface';
interface DefaultExpandIconProps<RecordType> {
prefixCls: string;

View File

@ -1,12 +1,14 @@
import RcTable, { Summary } from '../vc-table';
import { TableProps as RcTableProps, INTERNAL_HOOKS } from '../vc-table/Table';
import Spin, { SpinProps } from '../spin';
import type { TableProps as RcTableProps } from '../vc-table/Table';
import { INTERNAL_HOOKS } from '../vc-table/Table';
import type { SpinProps } from '../spin';
import Spin from '../spin';
import Pagination from '../pagination';
import { TooltipProps } from '../tooltip';
import type { TooltipProps } from '../tooltip';
import usePagination, { DEFAULT_PAGE_SIZE, getPaginationParam } from './hooks/usePagination';
import useLazyKVMap from './hooks/useLazyKVMap';
import { Breakpoint } from '../_util/responsiveObserve';
import {
import type { Breakpoint } from '../_util/responsiveObserve';
import type {
TableRowSelection,
GetRowKey,
ColumnType,
@ -26,24 +28,28 @@ import useSelection, {
SELECTION_INVERT,
SELECTION_NONE,
} from './hooks/useSelection';
import useSorter, { getSortData, SortState } from './hooks/useSorter';
import useFilter, { getFilterData, FilterState } from './hooks/useFilter';
import type { SortState } from './hooks/useSorter';
import useSorter, { getSortData } from './hooks/useSorter';
import type { FilterState } from './hooks/useFilter';
import useFilter, { getFilterData } from './hooks/useFilter';
import useTitleColumns from './hooks/useTitleColumns';
import renderExpandIcon from './ExpandIcon';
import scrollTo from '../_util/scrollTo';
import defaultLocale from '../locale/en_US';
import Column from './Column';
import ColumnGroup from './ColumnGroup';
import { SizeType } from '../config-provider';
import type { SizeType } from '../config-provider';
import devWarning from '../vc-util/devWarning';
import type { PropType } from 'vue';
import { computed, defineComponent, ref, toRef, watchEffect } from 'vue';
import { DefaultRecordType } from '../vc-table/interface';
import type { DefaultRecordType } from '../vc-table/interface';
import useBreakpoint from '../_util/hooks/useBreakpoint';
import { convertChildrenToColumns } from '../vc-table/hooks/useColumns';
import useConfigInject from '../_util/hooks/useConfigInject';
import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
import classNames from '../_util/classNames';
import omit from '../_util/omit';
import { initDefaultProps } from '../_util/props-util';
export type { ColumnsType, TablePaginationConfig };
@ -74,6 +80,7 @@ export interface TableProps<RecordType = DefaultRecordType>
| 'columns'
| 'scroll'
| 'emptyText'
| 'canExpandable'
> {
dropdownPrefixCls?: string;
dataSource?: RcTableProps<RecordType>['data'];
@ -100,9 +107,76 @@ export interface TableProps<RecordType = DefaultRecordType>
showSorterTooltip?: boolean | TooltipProps;
}
const tableProps = () => {
return {
prefixCls: { type: String as PropType<string> },
columns: { type: Array as PropType<ColumnsType> },
rowKey: { type: [String, Function] as PropType<TableProps['rowKey']> },
tableLayout: { type: String as PropType<TableProps['tableLayout']> },
rowClassName: { type: String as PropType<TableProps['rowClassName']> },
title: { type: Function as PropType<TableProps['title']> },
footer: { type: Function as PropType<TableProps['footer']> },
id: { type: String as PropType<TableProps['id']> },
showHeader: { type: Boolean as PropType<TableProps['showHeader']> },
components: { type: Object as PropType<TableProps['components']> },
customRow: { type: Function as PropType<TableProps['customRow']> },
customHeaderRow: { type: Function as PropType<TableProps['customHeaderRow']> },
direction: { type: String as PropType<TableProps['direction']> },
expandFixed: { type: Boolean as PropType<TableProps['expandFixed']> },
expandColumnWidth: { type: Number as PropType<TableProps['expandColumnWidth']> },
expandedRowKeys: { type: Array as PropType<TableProps['expandedRowKeys']> },
defaultExpandedRowKeys: { type: Array as PropType<TableProps['defaultExpandedRowKeys']> },
expandedRowRender: { type: Function as PropType<TableProps['expandedRowRender']> },
expandRowByClick: { type: Boolean as PropType<TableProps['expandRowByClick']> },
expandIcon: { type: Function as PropType<TableProps['expandIcon']> },
onExpand: { type: Function as PropType<TableProps['onExpand']> },
onExpandedRowsChange: { type: Function as PropType<TableProps['onExpandedRowsChange']> },
defaultExpandAllRows: { type: Boolean as PropType<TableProps['defaultExpandAllRows']> },
indentSize: { type: Number as PropType<TableProps['indentSize']> },
expandIconColumnIndex: { type: Number as PropType<TableProps['expandIconColumnIndex']> },
expandedRowClassName: { type: Function as PropType<TableProps['expandedRowClassName']> },
childrenColumnName: { type: String as PropType<TableProps['childrenColumnName']> },
rowExpandable: { type: Function as PropType<TableProps['rowExpandable']> },
sticky: { type: String as PropType<TableProps['sticky']> },
dropdownPrefixCls: String,
dataSource: { type: Array as PropType<RcTableProps['data']> },
pagination: { type: [Boolean, Object] as PropType<false | TablePaginationConfig> },
loading: { type: [Boolean, Object] as PropType<false | SpinProps> },
size: { type: String as PropType<SizeType> },
bordered: Boolean,
locale: { type: Object as PropType<TableLocale> },
onChange: {
type: Function as PropType<
(
pagination: TablePaginationConfig,
filters: Record<string, FilterValue | null>,
sorter: SorterResult | SorterResult[],
extra: TableCurrentDataSource,
) => void
>,
},
rowSelection: { type: Object as PropType<TableRowSelection> },
getPopupContainer: { type: Function as PropType<GetPopupContainer> },
scroll: {
type: Object as PropType<
RcTableProps['scroll'] & {
scrollToFirstRowOnChange?: boolean;
}
>,
},
sortDirections: { type: Array as PropType<SortOrder[]> },
showSorterTooltip: { type: [Boolean, Object] as PropType<boolean | TooltipProps> },
};
};
const InteralTable = defineComponent<TableProps>({
name: 'InteralTable',
props: {} as any,
props: initDefaultProps(tableProps(), {
rowKey: 'key',
}) as any,
inheritAttrs: false,
emits: [],
slots: ['emptyText', 'expandIcon', 'title', 'footer', 'summary'],
@ -173,7 +247,7 @@ const InteralTable = defineComponent<TableProps>({
const triggerOnChange = (
info: Partial<ChangeEventInfo>,
action: TableAction,
reset: boolean = false,
reset = false,
) => {
const { pagination, scroll, onChange } = props;
const changeInfo = {

View File

@ -6,12 +6,18 @@ import Checkbox from '../../../checkbox';
import Radio from '../../../radio';
import Dropdown from '../../../dropdown';
import Empty from '../../../empty';
import { ColumnType, ColumnFilterItem, Key, TableLocale, GetPopupContainer } from '../../interface';
import type {
ColumnType,
ColumnFilterItem,
Key,
TableLocale,
GetPopupContainer,
} from '../../interface';
import FilterDropdownMenuWrapper from './FilterWrapper';
import { FilterState } from '.';
import type { FilterState } from '.';
import { computed, defineComponent, onBeforeUnmount, ref } from 'vue';
import classNames from 'ant-design-vue/es/_util/classNames';
import useConfigInject from 'ant-design-vue/es/_util/hooks/useConfigInject';
import classNames from '../../../_util/classNames';
import useConfigInject from '../../../_util/hooks/useConfigInject';
const { SubMenu, Item: MenuItem } = Menu;

View File

@ -1,8 +1,9 @@
import { DefaultRecordType } from 'ant-design-vue/es/vc-table/interface';
import devWarning from 'ant-design-vue/es/vc-util/devWarning';
import useState from 'ant-design-vue/es/_util/hooks/useState';
import { computed, Ref } from 'vue';
import {
import type { DefaultRecordType } from '../../../vc-table/interface';
import devWarning from '../../../vc-util/devWarning';
import useState from '../../../_util/hooks/useState';
import type { Ref } from 'vue';
import { computed } from 'vue';
import type {
TransformColumns,
ColumnsType,
ColumnType,

View File

@ -1,4 +1,4 @@
import useState from 'ant-design-vue/es/_util/hooks/useState';
import useState from '../../_util/hooks/useState';
import type { Ref } from 'vue';
import { computed } from 'vue';
import type { PaginationProps } from '../../pagination';

View File

@ -1,20 +1,22 @@
import DownOutlined from '@ant-design/icons-vue/DownOutlined';
import { DataNode } from 'ant-design-vue/es/tree';
import { INTERNAL_COL_DEFINE } from 'ant-design-vue/es/vc-table';
import { FixedType } from 'ant-design-vue/es/vc-table/interface';
import { GetCheckDisabled } from 'ant-design-vue/es/vc-tree/interface';
import { arrAdd, arrDel } from 'ant-design-vue/es/vc-tree/util';
import { conductCheck } from 'ant-design-vue/es/vc-tree/utils/conductUtil';
import { convertDataToEntities } from 'ant-design-vue/es/vc-tree/utils/treeUtil';
import devWarning from 'ant-design-vue/es/vc-util/devWarning';
import useMergedState from 'ant-design-vue/es/_util/hooks/useMergedState';
import useState from 'ant-design-vue/es/_util/hooks/useState';
import { computed, ref, Ref, watchEffect } from 'vue';
import Checkbox, { CheckboxProps } from '../../checkbox';
import type { DataNode } from '../../tree';
import { INTERNAL_COL_DEFINE } from '../../vc-table';
import type { FixedType } from '../../vc-table/interface';
import type { GetCheckDisabled } from '../../vc-tree/interface';
import { arrAdd, arrDel } from '../../vc-tree/util';
import { conductCheck } from '../../vc-tree/utils/conductUtil';
import { convertDataToEntities } from '../../vc-tree/utils/treeUtil';
import devWarning from '../../vc-util/devWarning';
import useMergedState from '../../_util/hooks/useMergedState';
import useState from '../../_util/hooks/useState';
import type { Ref } from 'vue';
import { computed, ref, watchEffect } from 'vue';
import type { CheckboxProps } from '../../checkbox';
import Checkbox from '../../checkbox';
import Dropdown from '../../dropdown';
import Menu from '../../menu';
import Radio from '../../radio';
import {
import type {
TableRowSelection,
Key,
ColumnsType,
@ -474,8 +476,8 @@ export default function useSelection<RecordType>(
onChange={({ nativeEvent }) => {
const { shiftKey } = nativeEvent;
let startIndex: number = -1;
let endIndex: number = -1;
let startIndex = -1;
let endIndex = -1;
// Get range of this
if (shiftKey && checkStrictly) {

View File

@ -1,6 +1,6 @@
import CaretDownOutlined from '@ant-design/icons-vue/CaretDownOutlined';
import CaretUpOutlined from '@ant-design/icons-vue/CaretUpOutlined';
import {
import type {
TransformColumns,
ColumnsType,
Key,
@ -12,12 +12,14 @@ import {
ColumnGroupType,
TableLocale,
} from '../interface';
import Tooltip, { TooltipProps } from '../../tooltip';
import type { TooltipProps } from '../../tooltip';
import Tooltip from '../../tooltip';
import { getColumnKey, getColumnPos, renderColumnTitle } from '../util';
import classNames from 'ant-design-vue/es/_util/classNames';
import { computed, Ref } from 'vue';
import useState from 'ant-design-vue/es/_util/hooks/useState';
import { DefaultRecordType } from 'ant-design-vue/es/vc-table/interface';
import classNames from '../../_util/classNames';
import type { Ref } from 'vue';
import { computed } from 'vue';
import useState from '../../_util/hooks/useState';
import type { DefaultRecordType } from '../../vc-table/interface';
const ASCEND = 'ascend';
const DESCEND = 'descend';

View File

@ -1,5 +1,5 @@
import { Ref } from 'vue';
import { TransformColumns, ColumnTitleProps, ColumnsType } from '../interface';
import type { Ref } from 'vue';
import type { TransformColumns, ColumnTitleProps, ColumnsType } from '../interface';
import { renderColumnTitle } from '../util';
function fillTitle<RecordType>(

View File

@ -1,8 +1,8 @@
import Table from './Table';
import Column from './Column';
import ColumnGroup from './ColumnGroup';
import type Column from './Column';
import type ColumnGroup from './ColumnGroup';
import type { TableProps, TablePaginationConfig } from './Table';
import { App } from 'vue';
import type { App } from 'vue';
export type { ColumnProps } from './Column';
export type { ColumnsType, ColumnType, ColumnGroupType } from './interface';

View File

@ -8,9 +8,10 @@ import type {
import type { TooltipProps } from '../tooltip';
import type { CheckboxProps } from '../checkbox';
import type { PaginationProps } from '../pagination';
import { Breakpoint } from '../_util/responsiveObserve';
import { INTERNAL_SELECTION_ITEM } from './hooks/useSelection';
import { tuple, VueNode } from '../_util/type';
import type { Breakpoint } from '../_util/responsiveObserve';
import type { INTERNAL_SELECTION_ITEM } from './hooks/useSelection';
import type { VueNode } from '../_util/type';
import { tuple } from '../_util/type';
// import { TableAction } from './Table';
export type { GetRowKey, ExpandableConfig };
@ -136,7 +137,7 @@ export type SelectionSelectFn<T> = (
nativeEvent: Event,
) => void;
export interface TableRowSelection<T> {
export interface TableRowSelection<T = DefaultRecordType> {
/** Keep the selection keys in list even the key not exist in `dataSource` anymore */
preserveSelectedRowKeys?: boolean;
type?: RowSelectionType;
@ -169,7 +170,7 @@ export type TransformColumns<RecordType> = (
columns: ColumnsType<RecordType>,
) => ColumnsType<RecordType>;
export interface TableCurrentDataSource<RecordType> {
export interface TableCurrentDataSource<RecordType = DefaultRecordType> {
currentDataSource: RecordType[];
action: TableAction;
}

View File

@ -5,8 +5,8 @@ import ExpandedRow from './ExpandedRow';
import { computed, defineComponent, ref, watchEffect } from 'vue';
import { useInjectTable } from '../context/TableContext';
import { useInjectBody } from '../context/BodyContext';
import classNames from 'ant-design-vue/es/_util/classNames';
import { parseStyleText } from 'ant-design-vue/es/_util/props-util';
import classNames from '../../_util/classNames';
import { parseStyleText } from '../../_util/props-util';
export interface BodyRowProps<RecordType> {
record: RecordType;

View File

@ -1,4 +1,4 @@
import VCResizeObserver from 'ant-design-vue/es/vc-resize-observer';
import VCResizeObserver from '../../vc-resize-observer';
import type { Key } from '../interface';
export interface MeasureCellProps {

View File

@ -1,5 +1,5 @@
import classNames from 'ant-design-vue/es/_util/classNames';
import { isValidElement, parseStyleText } from 'ant-design-vue/es/_util/props-util';
import classNames from '../../_util/classNames';
import { isValidElement, parseStyleText } from '../../_util/props-util';
import type { CSSProperties, HTMLAttributes } from 'vue';
import { defineComponent } from 'vue';

View File

@ -13,7 +13,7 @@ import {
watchEffect,
} from 'vue';
import { useInjectTable } from '../context/TableContext';
import classNames from 'ant-design-vue/es/_util/classNames';
import classNames from '../../_util/classNames';
function useColumnWidth(colWidthsRef: Ref<readonly number[]>, columCountRef: Ref<number>) {
return computed(() => {

View File

@ -1,4 +1,4 @@
import classNames from 'ant-design-vue/es/_util/classNames';
import classNames from '../../_util/classNames';
import { computed, defineComponent } from 'vue';
import { useInjectTable } from '../context/TableContext';
import type {

View File

@ -242,8 +242,7 @@ export default defineComponent<TableProps>({
});
const innerExpandedKeys = ref([]);
// defalutXxxx
const stop = watchEffect(() => {
if (props.defaultExpandedRowKeys) {
innerExpandedKeys.value = props.defaultExpandedRowKeys;
}
@ -254,6 +253,10 @@ export default defineComponent<TableProps>({
mergedChildrenColumnName.value,
);
}
});
// defalutXxxx
stop();
const mergedExpandedKeys = computed(
() => new Set(props.expandedRowKeys || innerExpandedKeys.value || []),
);

View File

@ -1,4 +1,4 @@
import { warning } from 'ant-design-vue/es/vc-util/warning';
import { warning } from '../../vc-util/warning';
import type { ComputedRef, Ref } from 'vue';
import { computed, watchEffect } from 'vue';
import type {

View File

@ -1,39 +1,105 @@
<template>
<div>
<demo />
</div>
<a-table :columns="columns" :data-source="data">
<template #name="{ text }">
<a>{{ text }}</a>
</template>
<template #customTitle>
<span>
<smile-outlined />
Name
</span>
</template>
<template #tags="{ text: tags }">
<span>
<a-tag
v-for="tag in tags"
:key="tag"
:color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
>
{{ tag.toUpperCase() }}
</a-tag>
</span>
</template>
<template #action="{ record }">
<span>
<a>Invite {{ record.name }}</a>
<a-divider type="vertical" />
<a>Delete</a>
<a-divider type="vertical" />
<a class="ant-dropdown-link">
More actions
<down-outlined />
</a>
</span>
</template>
</a-table>
</template>
<script>
<script lang="ts">
import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
import demo from '../components/popover/demo/index.vue';
// import Affix from '../components/affix';
const columns = [
{
dataIndex: 'name',
key: 'name',
slots: { title: 'customTitle', customRender: 'name' },
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
slots: { customRender: 'tags' },
},
{
title: 'Action',
key: 'action',
slots: { customRender: 'action' },
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
export default defineComponent({
components: {
demo,
// Affix,
SmileOutlined,
DownOutlined,
},
data() {
setup() {
return {
visible: false,
pStyle: {
fontSize: '16px',
color: 'rgba(0,0,0,0.85)',
lineHeight: '24px',
display: 'block',
marginBottom: '16px',
},
pStyle2: {
marginBottom: '24px',
},
data,
columns,
};
},
methods: {
showDrawer() {
this.visible = true;
},
onClose() {
this.visible = false;
},
},
});
</script>