feat: update table

pull/2682/head
tanjinzhou 2020-07-23 18:34:24 +08:00
parent 98733252c1
commit b4980867f4
26 changed files with 421 additions and 518 deletions

View File

@ -88,11 +88,11 @@ export default function connect(mapStateToProps) {
store,
ref: 'wrappedInstance',
};
const slots = {};
for (let [key, value] of Object.entries($slots)) {
slots[key] = () => value();
}
return createVNode(WrappedComponent, wrapProps, slots);
// const slots = {};
// for (let [key, value] of Object.entries($slots)) {
// slots[key] = () => value();
// }
return createVNode(WrappedComponent, wrapProps, $slots);
},
};
return Connect;

View File

@ -3,4 +3,7 @@ import { ColumnProps } from './interface';
export default {
name: 'ATableColumn',
props: ColumnProps,
render() {
return null;
},
};

View File

@ -6,4 +6,7 @@ export default {
title: PropTypes.any,
},
__ANT_TABLE_COLUMN_GROUP: true,
render() {
return null;
},
};

View File

@ -1,13 +1,25 @@
export default {
name: 'FilterDropdownMenuWrapper',
methods: {
handelClick(e) {
e.stopPropagation();
//this.$emit('click', e);
},
},
render() {
const { $slots, handelClick } = this;
return <div onClick={handelClick}>{$slots.default}</div>;
},
// export default {
// name: 'FilterDropdownMenuWrapper',
// methods: {
// handelClick(e) {
// e.stopPropagation();
// //this.$emit('click', e);
// },
// },
// render() {
// const { $slots, handelClick } = this;
// return <div onClick={handelClick}>{$slots.default}</div>;
// },
// };
const FilterDropdownMenuWrapper = (_, { attrs, slots }) => {
return (
<div class={attrs.class} onClick={e => e.stopPropagation()}>
{slots.default?.()}
</div>
);
};
FilterDropdownMenuWrapper.inheritAttrs = false;
export default FilterDropdownMenuWrapper;

View File

@ -2,11 +2,12 @@ import Checkbox from '../checkbox';
import Radio from '../radio';
import { SelectionBoxProps } from './interface';
import BaseMixin from '../_util/BaseMixin';
import { getOptionProps, getListeners } from '../_util/props-util';
import { getOptionProps } from '../_util/props-util';
export default {
name: 'SelectionBox',
mixins: [BaseMixin],
inheritAttrs: false,
props: SelectionBoxProps,
data() {
return {
@ -46,17 +47,14 @@ export default {
},
render() {
const { type, rowIndex, ...rest } = getOptionProps(this);
const { type, rowIndex, ...rest } = { ...getOptionProps(this), ...this.$attrs };
const { checked } = this;
const checkboxProps = {
props: {
checked,
...rest,
},
on: getListeners(this),
checked,
...rest,
};
if (type === 'radio') {
checkboxProps.props.value = rowIndex;
checkboxProps.value = rowIndex;
return <Radio {...checkboxProps} />;
}
return <Checkbox {...checkboxProps} />;

View File

@ -90,6 +90,7 @@ function getCheckState(props) {
export default {
name: 'SelectionCheckboxAll',
mixins: [BaseMixin],
inheritAttrs: false,
props: SelectionCheckboxAllProps,
data() {
const { $props: props } = this;
@ -136,7 +137,7 @@ export default {
// type should be 'every' | 'some'
if (type === 'every' || type === 'some') {
return byDefaultChecked
? data[type]((item, i) => getCheckboxPropsByItem(item, i).props.defaultChecked)
? data[type]((item, i) => getCheckboxPropsByItem(item, i).defaultChecked)
: data[type](
(item, i) => store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0,
);
@ -207,8 +208,7 @@ export default {
customSelections =
newSelections.length > 0 ? (
<Dropdown getPopupContainer={getPopupContainer}>
<template slot="overlay">{menu}</template>
<Dropdown getPopupContainer={getPopupContainer} overlay={menu}>
<div class={`${selectionPrefixCls}-down`}>
<DownOutlined />
</div>

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import CaretUpFilled from '@ant-design/icons-vue/CaretUpFilled';
import CaretDownFilled from '@ant-design/icons-vue/CaretDownFilled';
import VcTable, { INTERNAL_COL_DEFINE } from '../vc-table';
@ -11,7 +12,7 @@ import Column from './Column';
import ColumnGroup from './ColumnGroup';
import createBodyRow from './createBodyRow';
import { flatArray, treeMap, flatFilter } from './util';
import { initDefaultProps, mergeProps, getOptionProps, getListeners } from '../_util/props-util';
import { initDefaultProps, getOptionProps } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin';
import { ConfigConsumerProps } from '../config-provider';
import { TableProps } from './interface';
@ -110,9 +111,10 @@ function isFiltersChanged(state, filters) {
export default {
name: 'Table',
mixins: [BaseMixin],
inheritAttrs: false,
Column,
ColumnGroup,
mixins: [BaseMixin],
props: initDefaultProps(TableProps, {
dataSource: [],
useFixedHeader: false,
@ -128,15 +130,11 @@ export default {
childrenColumnName: 'children',
}),
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
// CheckboxPropsCache: {
// [key: string]: any;
// };
// store: Store;
// columns: ColumnProps<T>[];
// components: TableComponents;
data() {
// this.columns = props.columns || normalizeColumns(props.children)
@ -145,7 +143,7 @@ export default {
!props.expandedRowRender || !('scroll' in props),
'`expandedRowRender` and `scroll` are not compatible. Please use one of them at one time.',
);
this.CheckboxPropsCache = {};
this.checkboxPropsCache = {};
this.store = createStore({
selectedRowKeys: getRowSelection(this.$props).selectedRowKeys || [],
@ -185,7 +183,7 @@ export default {
});
const { rowSelection } = this;
if (rowSelection && val.getCheckboxProps !== rowSelection.getCheckboxProps) {
this.CheckboxPropsCache = {};
this.checkboxPropsCache = {};
}
} else if (oldVal && !val) {
this.store.setState({
@ -200,7 +198,7 @@ export default {
this.store.setState({
selectionDirty: false,
});
this.CheckboxPropsCache = {};
this.checkboxPropsCache = {};
},
columns(val) {
@ -236,18 +234,20 @@ export default {
}
},
methods: {
setTableRef(table) {
this.vcTable = table;
},
getCheckboxPropsByItem(item, index) {
const rowSelection = getRowSelection(this.$props);
if (!rowSelection.getCheckboxProps) {
return { props: {} };
return {};
}
const key = this.getRecordKey(item, index);
// Cache checkboxProps
if (!this.CheckboxPropsCache[key]) {
this.CheckboxPropsCache[key] = rowSelection.getCheckboxProps(item);
if (!this.checkboxPropsCache[key]) {
this.checkboxPropsCache[key] = rowSelection.getCheckboxProps(item) || {};
}
this.CheckboxPropsCache[key].props = this.CheckboxPropsCache[key].props || {};
return this.CheckboxPropsCache[key];
return this.checkboxPropsCache[key];
},
getDefaultSelection() {
@ -256,9 +256,7 @@ export default {
return [];
}
return this.getFlatData()
.filter(
(item, rowIndex) => this.getCheckboxPropsByItem(item, rowIndex).props.defaultChecked,
)
.filter((item, rowIndex) => this.getCheckboxPropsByItem(item, rowIndex).defaultChecked)
.map((record, rowIndex) => this.getRecordKey(record, rowIndex));
},
@ -447,13 +445,7 @@ export default {
onRow(prefixCls, record, index) {
const { customRow } = this;
const custom = customRow ? customRow(record, index) : {};
return mergeProps(custom, {
props: {
prefixCls,
store: this.store,
rowKey: this.getRecordKey(record, index),
},
});
return { ...custom, prefixCls, store: this.store, rowKey: this.getRecordKey(record, index) };
},
setSelectedRowKeys(selectedRowKeys, selectionInfo) {
@ -490,19 +482,19 @@ export default {
},
generatePopupContainerFunc(getPopupContainer) {
const { scroll } = this.$props;
const table = this.$refs.vcTable;
const table = this.vcTable;
if (getPopupContainer) {
return getPopupContainer;
}
// Use undefined to let rc component use default logic.
return scroll && table ? () => table.getTableNode() : undefined;
return scroll && table ? () => table.tableNode : undefined;
},
scrollToFirstRow() {
const { scroll } = this.$props;
if (scroll && scroll.scrollToFirstRowOnChange !== false) {
scrollTo(0, {
getContainer: () => {
return this.$refs.vcTable.getBodyTable();
return this.vcTable.ref_bodyTable;
},
});
}
@ -681,7 +673,7 @@ export default {
: this.getDefaultSelection();
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const changeableRowKeys = data
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).props.disabled)
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled)
.map((item, i) => this.getRecordKey(item, i));
const changeRowKeys = [];
@ -939,21 +931,17 @@ export default {
const position = pagination.position || 'bottom';
const total = pagination.total || this.filterDataCnt;
const { class: cls, style, onChange, onShowSizeChange, ...restProps } = pagination; // eslint-disable-line
const paginationProps = mergeProps({
const paginationProps = {
key: `pagination-${paginationPosition}`,
class: classNames(cls, `${prefixCls}-pagination`),
props: {
...restProps,
total,
size,
current: this.getMaxCurrent(total),
},
...restProps,
total,
size,
current: this.getMaxCurrent(total),
style,
on: {
change: this.handlePageChange,
showSizeChange: this.handleShowSizeChange,
},
});
onChange: this.handlePageChange,
onShowSizeChange: this.handleShowSizeChange,
};
return total > 0 && (position === paginationPosition || position === 'both') ? (
<Pagination {...paginationProps} />
) : null;
@ -967,20 +955,14 @@ export default {
? this.handleRadioSelect(record, index, e)
: this.handleSelect(record, index, e);
};
const selectionBoxProps = mergeProps(
{
props: {
type,
store: this.store,
rowIndex: rowKey,
defaultSelection: this.getDefaultSelection(),
},
on: {
change: handleChange,
},
},
props,
);
const selectionBoxProps = {
type,
store: this.store,
rowIndex: rowKey,
defaultSelection: this.getDefaultSelection(),
onChange: handleChange,
...props,
};
return (
<span onClick={stopPropagation}>
@ -996,7 +978,7 @@ export default {
if (rowSelection) {
const data = this.getFlatCurrentPageData().filter((item, index) => {
if (rowSelection.getCheckboxProps) {
return !this.getCheckboxPropsByItem(item, index).props.disabled;
return !this.getCheckboxPropsByItem(item, index).disabled;
}
return true;
});
@ -1016,7 +998,7 @@ export default {
};
if (rowSelection.type !== 'radio') {
const checkboxAllDisabled = data.every(
(item, index) => this.getCheckboxPropsByItem(item, index).props.disabled,
(item, index) => this.getCheckboxPropsByItem(item, index).disabled,
);
selectionColumn.title = selectionColumn.title || (
<SelectionCheckboxAll
@ -1111,10 +1093,9 @@ export default {
...column.customHeaderCell(col),
};
}
colProps.on = colProps.on || {};
// Add sorter logic
const onHeaderCellClick = colProps.on.click;
colProps.on.click = (...args) => {
const onHeaderCellClick = colProps.onClick;
colProps.onClick = (...args) => {
this.toggleSortOrder(column);
if (onHeaderCellClick) {
onHeaderCellClick(...args);
@ -1167,7 +1148,10 @@ export default {
getPopupContainer: contextGetPopupContainer,
transformCellText,
}) {
const { showHeader, locale, getPopupContainer, ...restProps } = getOptionProps(this);
const { showHeader, locale, getPopupContainer, ...restProps } = {
...getOptionProps(this),
...this.$attrs,
};
const data = this.getCurrentPageData();
const expandIconAsCell = this.expandedRowRender && this.expandIconAsCell !== false;
@ -1177,7 +1161,7 @@ export default {
// Merge too locales
const mergedLocale = { ...contextLocale, ...locale };
if (!locale || !locale.emptyText) {
mergedLocale.emptyText = renderEmpty(h, 'Table');
mergedLocale.emptyText = renderEmpty('Table');
}
const classString = classNames({
@ -1210,23 +1194,20 @@ export default {
}
const vcTableProps = {
key: 'table',
props: {
expandIcon: this.renderExpandIcon(prefixCls),
...restProps,
customRow: (record, index) => this.onRow(prefixCls, record, index),
components: this.sComponents,
prefixCls,
data,
columns,
showHeader,
expandIconColumnIndex,
expandIconAsCell,
emptyText: mergedLocale.emptyText,
transformCellText,
},
on: getListeners(this),
expandIcon: this.renderExpandIcon(prefixCls),
...restProps,
customRow: (record, index) => this.onRow(prefixCls, record, index),
components: this.sComponents,
prefixCls,
data,
columns,
showHeader,
expandIconColumnIndex,
expandIconAsCell,
emptyText: mergedLocale.emptyText,
transformCellText,
class: classString,
ref: 'vcTable',
ref: this.setTableRef,
};
return <VcTable {...vcTableProps} />;
},
@ -1248,13 +1229,7 @@ export default {
let loading = this.loading;
if (typeof loading === 'boolean') {
loading = {
props: {
spinning: loading,
},
};
} else {
loading = {
props: { ...loading },
spinning: loading,
};
}
const getPrefixCls = this.configProvider.getPrefixCls;
@ -1293,8 +1268,9 @@ export default {
? `${paginationPatchClass} ${prefixCls}-spin-holder`
: '',
};
const { class: className, style } = this.$attrs;
return (
<div class={classNames(`${prefixCls}-wrapper`)}>
<div class={classNames(`${prefixCls}-wrapper`, className)} style={style}>
<Spin {...spinProps}>
{this.renderPagination(prefixCls, 'top')}
{table}

View File

@ -1,7 +1,8 @@
import PropTypes from '../_util/vue-types';
import { Store } from './createStore';
import { getListeners } from '../_util/props-util';
import { getSlot } from '../_util/props-util';
import Omit from 'omit.js';
const BodyRowProps = {
store: Store,
@ -12,6 +13,7 @@ const BodyRowProps = {
export default function createBodyRow(Component = 'tr') {
const BodyRow = {
name: 'BodyRow',
inheritAttrs: false,
props: BodyRowProps,
data() {
const { selectedRowKeys } = this.store.getState();
@ -44,13 +46,20 @@ export default function createBodyRow(Component = 'tr') {
},
render() {
const rowProps = Omit({ ...this.$props, ...this.$attrs }, [
'prefixCls',
'rowKey',
'store',
'class',
]);
const className = {
[`${this.prefixCls}-row-selected`]: this.selected,
[this.$attrs.class]: !!this.$attrs.class,
};
return (
<Component class={className} {...{ on: getListeners(this) }}>
{this.$slots.default}
<Component class={className} {...rowProps}>
{getSlot(this)}
</Component>
);
},

View File

@ -20,6 +20,7 @@ function stopPropagation(e) {
export default {
name: 'FilterMenu',
mixins: [BaseMixin],
inheritAttrs: false,
props: initDefaultProps(FilterMenuProps, {
handleFilter() {},
column: {},
@ -230,10 +231,9 @@ export default {
}
if (filterIcon.length === 1 && isValidElement(filterIcon[0])) {
return cloneElement(filterIcon[0], {
on: {
click: stopPropagation,
},
class: classNames(`${prefixCls}-icon`, dropdownIconClass),
title: filterIcon.props?.title || locale.filterTitle,
onClick: stopPropagation,
class: classNames(`${prefixCls}-icon`, dropdownIconClass, filterIcon.props?.class),
});
}
return <span class={classNames(`${prefixCls}-icon`, dropdownIconClass)}>{filterIcon}</span>;
@ -321,8 +321,8 @@ export default {
onVisibleChange={this.onVisibleChange}
getPopupContainer={getPopupContainer}
forceRender
overlay={menus}
>
<template slot="overlay">{menus}</template>
{this.renderFilterIcon()}
</Dropdown>
);

View File

@ -1,53 +1,32 @@
import T from './Table';
import ref from 'vue-ref';
import Vue from 'vue';
import {
getOptionProps,
getKey,
getClass,
getStyle,
getEvents,
getSlotOptions,
camelize,
getSlots,
getListeners,
} from '../_util/props-util';
import Base from '../base';
Vue.use(ref, { name: 'ant-ref' });
import { getOptionProps, getKey, getPropsData, getSlot } from '../_util/props-util';
const Table = {
name: 'ATable',
Column: T.Column,
ColumnGroup: T.ColumnGroup,
props: T.props,
inheritAttrs: false,
methods: {
normalize(elements = []) {
const columns = [];
elements.forEach(element => {
if (!element.tag) {
if (!element) {
return;
}
const key = getKey(element);
const style = getStyle(element);
const cls = getClass(element);
const props = getOptionProps(element);
const events = getEvents(element);
const listeners = {};
Object.keys(events).forEach(e => {
const k = `on-${e}`;
listeners[camelize(k)] = events[e];
});
const { default: children, ...restSlots } = getSlots(element);
const column = { ...restSlots, ...props, style, class: cls, ...listeners };
const style = element.props?.style || {};
const cls = element.props?.class || '';
const props = getPropsData(element);
const { default: children, ...restSlots } = element.children;
const column = { ...restSlots, ...props, style, class: cls };
if (key) {
column.key = key;
}
if (getSlotOptions(element).__ANT_TABLE_COLUMN_GROUP) {
if (element.type?.__ANT_TABLE_COLUMN_GROUP) {
column.children = this.normalize(typeof children === 'function' ? children() : children);
} else {
const customRender =
element.data && element.data.scopedSlots && element.data.scopedSlots.default;
const customRender = element.children?.default;
column.customRender = column.customRender || customRender;
}
columns.push(column);
@ -56,22 +35,16 @@ const Table = {
},
updateColumns(cols = []) {
const columns = [];
const { $slots, $scopedSlots } = this;
const { $slots } = this;
cols.forEach(col => {
const { slots = {}, scopedSlots = {}, ...restProps } = col;
const { slots = {}, ...restProps } = col;
const column = {
...restProps,
};
Object.keys(slots).forEach(key => {
const name = slots[key];
if (column[key] === undefined && $slots[name]) {
column[key] = $slots[name].length === 1 ? $slots[name][0] : $slots[name];
}
});
Object.keys(scopedSlots).forEach(key => {
const name = scopedSlots[key];
if (column[key] === undefined && $scopedSlots[name]) {
column[key] = $scopedSlots[name];
column[key] = $slots[name];
}
});
// if (slotScopeName && $scopedSlots[slotScopeName]) {
@ -86,36 +59,32 @@ const Table = {
},
},
render() {
const { $slots, normalize, $scopedSlots } = this;
const props = getOptionProps(this);
const columns = props.columns ? this.updateColumns(props.columns) : normalize($slots.default);
const { normalize, $slots } = this;
const props = { ...getOptionProps(this), ...this.$attrs };
const columns = props.columns ? this.updateColumns(props.columns) : normalize(getSlot(this));
let { title, footer } = props;
const {
title: slotTitle,
footer: slotFooter,
expandedRowRender = props.expandedRowRender,
} = $scopedSlots;
} = $slots;
title = title || slotTitle;
footer = footer || slotFooter;
const tProps = {
props: {
...props,
columns,
title,
footer,
expandedRowRender,
},
on: getListeners(this),
...props,
columns,
title,
footer,
expandedRowRender,
};
return <T {...tProps} />;
},
};
/* istanbul ignore next */
Table.install = function(Vue) {
Vue.use(Base);
Vue.component(Table.name, Table);
Vue.component(Table.Column.name, Table.Column);
Vue.component(Table.ColumnGroup.name, Table.ColumnGroup);
Table.install = function(app) {
app.component(Table.name, Table);
app.component(Table.Column.name, Table.Column);
app.component(Table.ColumnGroup.name, Table.ColumnGroup);
};
export default Table;

View File

@ -1,79 +1,37 @@
// base rc-table 6.10.9
import T from './src/Table';
import Table from './src/Table';
import Column from './src/Column';
import ColumnGroup from './src/ColumnGroup';
import {
getOptionProps,
getKey,
getClass,
getStyle,
getEvents,
getSlotOptions,
camelize,
getSlots,
getListeners,
} from '../_util/props-util';
import { INTERNAL_COL_DEFINE } from './src/utils';
const Table = {
name: 'Table',
Column,
ColumnGroup,
props: T.props,
methods: {
getTableNode() {
return this.$refs.table.tableNode;
},
getBodyTable() {
return this.$refs.table.ref_bodyTable;
},
normalize(elements = []) {
const columns = [];
elements.forEach(element => {
if (!element.tag) {
return;
}
const key = getKey(element);
const style = getStyle(element);
const cls = getClass(element);
const props = getOptionProps(element);
const events = getEvents(element);
const listeners = {};
Object.keys(events).forEach(e => {
const k = `on-${e}`;
listeners[camelize(k)] = events[e];
});
const { default: children, title } = getSlots(element);
const column = { title, ...props, style, class: cls, ...listeners };
if (key) {
column.key = key;
}
if (getSlotOptions(element).isTableColumnGroup) {
column.children = this.normalize(typeof children === 'function' ? children() : children);
} else {
const customRender =
element.data && element.data.scopedSlots && element.data.scopedSlots.default;
column.customRender = column.customRender || customRender;
}
columns.push(column);
});
return columns;
},
},
render() {
const { $slots, normalize } = this;
const props = getOptionProps(this);
const columns = props.columns || normalize($slots.default);
const tProps = {
props: {
...props,
columns,
},
on: getListeners(this),
ref: 'table',
};
return <T {...tProps} />;
},
};
// const Table = {
// name: 'Table',
// inheritAttrs: false,
// Column,
// ColumnGroup,
// props: T.props,
// methods: {
// getTableNode() {
// return this.table.tableNode;
// },
// getBodyTable() {
// return this.table.ref_bodyTable;
// },
// saveTable(node) {
// this.table = node;
// },
// },
// render() {
// const props = getOptionProps(this);
// const columns = props.columns;
// const tProps = {
// ...props,
// ...this.$attrs,
// columns,
// ref: this.saveTable,
// };
// return <T {...tProps} />;
// },
// };
export default Table;
export { Column, ColumnGroup, INTERNAL_COL_DEFINE };

View File

@ -1,14 +1,15 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import classNames from 'classnames';
import ColGroup from './ColGroup';
import TableHeader from './TableHeader';
import TableRow from './TableRow';
import ExpandableRow from './ExpandableRow';
import { mergeProps, getListeners } from '../../_util/props-util';
import { connect } from '../../_util/store';
function noop() {}
const BaseTable = {
name: 'BaseTable',
inheritAttrs: false,
props: {
fixed: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
columns: PropTypes.array.isRequired,
@ -20,8 +21,10 @@ const BaseTable = {
getRowKey: PropTypes.func,
isAnyColumnsFixed: PropTypes.bool,
},
inject: {
table: { default: () => ({}) },
setup() {
return {
table: inject('table', {}),
};
},
methods: {
getColumns(cols) {
@ -32,8 +35,8 @@ const BaseTable = {
...column,
className:
!!column.fixed && !fixed
? classNames(`${prefixCls}-fixed-columns-in-body`, column.className || column.class)
: column.className || column.class,
? classNames(`${prefixCls}-fixed-columns-in-body`, column.className, column.class)
: classNames(column.className, column.class),
}));
},
handleRowHover(isHover, key) {
@ -50,14 +53,13 @@ const BaseTable = {
childrenColumnName,
rowClassName,
customRow = noop,
} = this.table;
const {
rowClick: onRowClick = noop,
rowDoubleclick: onRowDoubleClick = noop,
rowContextmenu: onRowContextMenu = noop,
rowMouseenter: onRowMouseEnter = noop,
rowMouseleave: onRowMouseLeave = noop,
} = getListeners(this.table);
onRowClick = noop,
onRowDoubleClick = noop,
onRowContextMenu = noop,
onRowMouseEnter = noop,
onRowMouseLeave = noop,
rowRef,
} = { ...this.table.$attrs, ...this.table.$props, ...this.table.$data };
const { getRowKey, fixed, expander, isAnyColumnsFixed } = this;
const rows = [];
@ -70,7 +72,7 @@ const BaseTable = {
const onHoverProps = {};
if (columnManager.isAnyColumnsFixed()) {
onHoverProps.hover = this.handleRowHover;
onHoverProps.onHover = this.handleRowHover;
}
let leafColumns;
@ -85,56 +87,49 @@ const BaseTable = {
const rowPrefixCls = `${prefixCls}-row`;
const expandableRowProps = {
props: {
...expander.props,
fixed,
index: i,
prefixCls: rowPrefixCls,
record,
rowKey: key,
needIndentSpaced: expander.needIndentSpaced,
},
...expander.props,
fixed,
index: i,
prefixCls: rowPrefixCls,
record,
rowKey: key,
needIndentSpaced: expander.needIndentSpaced,
key,
on: {
// ...expander.on,
rowClick: onRowClick,
expandedChange: expander.handleExpandChange,
},
scopedSlots: {
default: expandableRow => {
const tableRowProps = mergeProps(
{
props: {
fixed,
indent,
record,
index: i,
prefixCls: rowPrefixCls,
childrenColumnName,
columns: leafColumns,
rowKey: key,
ancestorKeys,
components,
isAnyColumnsFixed,
customRow,
},
on: {
rowDoubleclick: onRowDoubleClick,
rowContextmenu: onRowContextMenu,
rowMouseenter: onRowMouseEnter,
rowMouseleave: onRowMouseLeave,
...onHoverProps,
},
class: className,
ref: `row_${i}_${indent}`,
},
expandableRow,
);
return <TableRow {...tableRowProps} />;
},
},
onRowClick,
onExpandedChange: expander.handleExpandChange,
};
const row = <ExpandableRow {...expandableRowProps} />;
const row = (
<ExpandableRow
{...expandableRowProps}
vSlots={{
default: expandableRow => {
const tableRowProps = {
fixed,
indent,
record,
index: i,
prefixCls: rowPrefixCls,
childrenColumnName,
columns: leafColumns,
rowKey: key,
ancestorKeys,
components,
isAnyColumnsFixed,
customRow,
onRowDoubleClick,
onRowContextMenu,
onRowMouseEnter,
onRowMouseLeave,
...onHoverProps,
class: className,
ref: rowRef(record, i, indent),
...expandableRow,
};
return <TableRow {...tableRowProps} />;
},
}}
/>
);
rows.push(row);
expander.renderRows(this.renderRows, rows, record, i, indent, fixed, key, ancestorKeys);

View File

@ -1,9 +1,11 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import { measureScrollbar } from './utils';
import BaseTable from './BaseTable';
export default {
name: 'BodyTable',
inheritAttrs: false,
props: {
fixed: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
columns: PropTypes.array.isRequired,
@ -14,8 +16,10 @@ export default {
expander: PropTypes.object.isRequired,
isAnyColumnsFixed: PropTypes.bool,
},
inject: {
table: { default: () => ({}) },
setup() {
return {
table: inject('table', {}),
};
},
render() {
const { prefixCls, scroll } = this.table;
@ -89,14 +93,7 @@ export default {
<div
class={`${prefixCls}-body-inner`}
style={innerBodyStyle}
{...{
directives: [
{
name: 'ant-ref',
value: saveRef(refName),
},
],
}}
ref={saveRef(refName)}
onWheel={handleWheel}
onScroll={handleBodyScroll}
>
@ -114,14 +111,7 @@ export default {
key="bodyTable"
class={`${prefixCls}-body`}
style={bodyStyle}
{...{
directives: [
{
name: 'ant-ref',
value: saveRef('bodyTable'),
},
],
}}
ref={saveRef('bodyTable')}
onWheel={handleWheel}
onScroll={handleBodyScroll}
>

View File

@ -1,14 +1,18 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import { INTERNAL_COL_DEFINE } from './utils';
export default {
name: 'ColGroup',
inheritAttrs: false,
props: {
fixed: PropTypes.string,
columns: PropTypes.array,
},
inject: {
table: { default: () => ({}) },
setup() {
return {
table: inject('table', {}),
};
},
render() {
const { fixed, table } = this;

View File

@ -1,20 +1,24 @@
import PropTypes from '../../_util/vue-types';
// import PropTypes from '../../_util/vue-types';
export default {
name: 'Column',
props: {
rowSpan: PropTypes.number,
colSpan: PropTypes.number,
title: PropTypes.any,
dataIndex: PropTypes.string,
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
ellipsis: PropTypes.bool,
fixed: PropTypes.oneOf([true, 'left', 'right']),
align: PropTypes.oneOf(['left', 'center', 'right']),
customRender: PropTypes.func,
className: PropTypes.string,
// onCellClick: PropTypes.func,
customCell: PropTypes.func,
customHeaderCell: PropTypes.func,
},
};
// export default {
// name: 'Column',
// props: {
// rowSpan: PropTypes.number,
// colSpan: PropTypes.number,
// title: PropTypes.any,
// dataIndex: PropTypes.string,
// width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
// ellipsis: PropTypes.bool,
// fixed: PropTypes.oneOf([true, 'left', 'right']),
// align: PropTypes.oneOf(['left', 'center', 'right']),
// customRender: PropTypes.func,
// className: PropTypes.string,
// // onCellClick: PropTypes.func,
// customCell: PropTypes.func,
// customHeaderCell: PropTypes.func,
// },
// };
const Column = () => null;
export default Column;

View File

@ -6,4 +6,7 @@ export default {
title: PropTypes.any,
},
isTableColumnGroup: true,
render() {
return null;
},
};

View File

@ -3,6 +3,7 @@ import BaseMixin from '../../_util/BaseMixin';
export default {
name: 'ExpandIcon',
mixins: [BaseMixin],
inheritAttrs: false,
props: {
record: PropTypes.object,
prefixCls: PropTypes.string,

View File

@ -2,10 +2,12 @@ import PropTypes from '../../_util/vue-types';
import ExpandIcon from './ExpandIcon';
import BaseMixin from '../../_util/BaseMixin';
import { connect } from '../../_util/store';
import { getSlot } from '../../_util/props-util';
const ExpandableRow = {
mixins: [BaseMixin],
name: 'ExpandableRow',
inheritAttrs: false,
props: {
prefixCls: PropTypes.string.isRequired,
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
@ -96,35 +98,22 @@ const ExpandableRow = {
},
render() {
const {
childrenColumnName,
expandedRowRender,
indentSize,
record,
fixed,
$scopedSlots,
expanded,
} = this;
const { childrenColumnName, expandedRowRender, indentSize, record, fixed, expanded } = this;
this.tempExpandIconAsCell = fixed !== 'right' ? this.expandIconAsCell : false;
this.tempExpandIconColumnIndex = fixed !== 'right' ? this.expandIconColumnIndex : -1;
const childrenData = record[childrenColumnName];
this.expandable = !!(childrenData || expandedRowRender);
const expandableRowProps = {
props: {
indentSize,
expanded, // not used in TableRow, but it's required to re-render TableRow when `expanded` changes
hasExpandIcon: this.hasExpandIcon,
renderExpandIcon: this.renderExpandIcon,
renderExpandIconCell: this.renderExpandIconCell,
},
on: {
rowClick: this.handleRowClick,
},
indentSize,
expanded, // not used in TableRow, but it's required to re-render TableRow when `expanded` changes
hasExpandIcon: this.hasExpandIcon,
renderExpandIcon: this.renderExpandIcon,
renderExpandIconCell: this.renderExpandIconCell,
onRowClick: this.handleRowClick,
};
return $scopedSlots.default && $scopedSlots.default(expandableRowProps);
return getSlot(this, 'default', expandableRowProps);
},
};

View File

@ -4,7 +4,7 @@ import { connect } from '../../_util/store';
import shallowEqual from 'shallowequal';
import TableRow from './TableRow';
import { remove } from './utils';
import { initDefaultProps, getOptionProps, getListeners } from '../../_util/props-util';
import { initDefaultProps, getOptionProps, getSlot } from '../../_util/props-util';
export const ExpandableTableProps = () => ({
expandIconAsCell: PropTypes.bool,
@ -29,6 +29,7 @@ export const ExpandableTableProps = () => ({
const ExpandableTable = {
name: 'ExpandableTable',
inheritAttrs: false,
mixins: [BaseMixin],
props: initDefaultProps(ExpandableTableProps(), {
expandIconAsCell: false,
@ -166,9 +167,7 @@ const ExpandableTable = {
const { expandedRowKeys } = this.store.getState();
const expanded = expandedRowKeys.includes(parentKey);
return {
attrs: {
colSpan: colCount,
},
props: { colSpan: colCount },
children:
fixed !== 'right' ? expandedRowRender(record, index, indent, expanded) : '&nbsp;',
};
@ -227,21 +226,18 @@ const ExpandableTable = {
},
render() {
const { data, childrenColumnName, $scopedSlots } = this;
const { data, childrenColumnName } = this;
const props = getOptionProps(this);
const needIndentSpaced = data.some(record => record[childrenColumnName]);
return (
$scopedSlots.default &&
$scopedSlots.default({
props,
on: getListeners(this),
needIndentSpaced,
renderRows: this.renderRows,
handleExpandChange: this.handleExpandChange,
renderExpandIndentCell: this.renderExpandIndentCell,
})
);
return getSlot(this, 'default', {
...props,
...this.$attrs,
needIndentSpaced,
renderRows: this.renderRows,
handleExpandChange: this.handleExpandChange,
renderExpandIndentCell: this.renderExpandIndentCell,
});
},
};

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import { measureScrollbar } from './utils';
import BaseTable from './BaseTable';
@ -5,6 +6,7 @@ import classNames from 'classnames';
export default {
name: 'HeadTable',
inheritAttrs: false,
props: {
fixed: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
columns: PropTypes.array.isRequired,
@ -12,8 +14,10 @@ export default {
handleBodyScrollLeft: PropTypes.func.isRequired,
expander: PropTypes.object.isRequired,
},
inject: {
table: { default: () => ({}) },
setup() {
return {
table: inject('table', {}),
};
},
render() {
const { columns, fixed, tableClassName, handleBodyScrollLeft, expander, table } = this;
@ -45,14 +49,7 @@ export default {
return (
<div
key="headTable"
{...{
directives: [
{
name: 'ant-ref',
value: fixed ? () => {} : saveRef('headTable'),
},
],
}}
ref={fixed ? () => {} : saveRef('headTable')}
class={classNames(`${prefixCls}-header`, {
[`${prefixCls}-hide-scrollbar`]: scrollbarWidth > 0,
})}

View File

@ -1,10 +1,11 @@
/* eslint-disable camelcase */
import { provide } from 'vue';
import shallowequal from 'shallowequal';
import merge from 'lodash/merge';
import classes from 'component-classes';
import classNames from 'classnames';
import PropTypes from '../../_util/vue-types';
import { debounce } from './utils';
import { debounce, getDataAndAriaProps } from './utils';
import warning from '../../_util/warning';
import addEventListener from '../../vc-util/Dom/addEventListener';
import { Provider, create } from '../../_util/store';
@ -12,12 +13,13 @@ import ColumnManager from './ColumnManager';
import HeadTable from './HeadTable';
import BodyTable from './BodyTable';
import ExpandableTable from './ExpandableTable';
import { initDefaultProps, getOptionProps, getListeners } from '../../_util/props-util';
import { initDefaultProps, getOptionProps } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
export default {
name: 'Table',
mixins: [BaseMixin],
inheritAttrs: false,
props: initDefaultProps(
{
data: PropTypes.array,
@ -41,7 +43,7 @@ export default {
emptyText: PropTypes.any,
scroll: PropTypes.object,
rowRef: PropTypes.func,
getBodyWrapper: PropTypes.func,
// getBodyWrapper: PropTypes.func,
components: PropTypes.shape({
table: PropTypes.any,
header: PropTypes.shape({
@ -144,19 +146,20 @@ export default {
// },
created() {
['rowClick', 'rowDoubleclick', 'rowContextmenu', 'rowMouseenter', 'rowMouseleave'].forEach(
name => {
warning(
getListeners(this)[name] === undefined,
`${name} is deprecated, please use customRow instead.`,
);
},
);
provide('table', this);
// ['rowClick', 'rowDoubleclick', 'rowContextmenu', 'rowMouseenter', 'rowMouseleave'].forEach(
// name => {
// warning(
// getListeners(this)[name] === undefined,
// `${name} is deprecated, please use customRow instead.`,
// );
// },
// );
warning(
this.getBodyWrapper === undefined,
'getBodyWrapper is deprecated, please use custom components instead.',
);
// warning(
// this.getBodyWrapper === undefined,
// 'getBodyWrapper is deprecated, please use custom components instead.',
// );
// this.columnManager = new ColumnManager(this.columns, this.$slots.default)
@ -541,11 +544,11 @@ export default {
},
render() {
const props = getOptionProps(this);
const props = { ...getOptionProps(this), ...this.$attrs };
const { columnManager, getRowKey } = this;
const prefixCls = props.prefixCls;
const tableClassName = classNames(props.prefixCls, {
const tableClassName = classNames(props.prefixCls, props.class, {
[`${prefixCls}-fixed-header`]: props.useFixedHeader || (props.scroll && props.scroll.y),
[`${prefixCls}-scroll-position-left ${prefixCls}-scroll-position-right`]:
this.scrollPosition === 'both',
@ -555,45 +558,38 @@ export default {
const hasLeftFixed = columnManager.isAnyColumnsLeftFixed();
const hasRightFixed = columnManager.isAnyColumnsRightFixed();
const dataAndAriaProps = getDataAndAriaProps(props);
const expandableTableProps = {
props: {
...props,
columnManager,
getRowKey,
},
on: getListeners(this),
scopedSlots: {
default: expander => {
this.expander = expander;
return (
<div
{...{
directives: [
{
name: 'ant-ref',
value: this.saveTableNodeRef,
},
],
}}
class={tableClassName}
// style={props.style}
// id={props.id}
>
{this.renderTitle()}
<div class={`${prefixCls}-content`}>
{this.renderMainTable()}
{hasLeftFixed && this.renderLeftFixedTable()}
{hasRightFixed && this.renderRightFixedTable()}
</div>
</div>
);
},
},
...props,
columnManager,
getRowKey,
};
return (
<Provider store={this.store}>
<ExpandableTable {...expandableTableProps} />
<ExpandableTable
{...expandableTableProps}
vSlots={{
default: expander => {
this.expander = expander;
return (
<div
ref={this.saveTableNodeRef}
class={tableClassName}
style={props.style}
id={props.id}
{...dataAndAriaProps}
>
{this.renderTitle()}
<div class={`${prefixCls}-content`}>
{this.renderMainTable()}
{hasLeftFixed && this.renderLeftFixedTable()}
{hasRightFixed && this.renderRightFixedTable()}
</div>
</div>
);
},
}}
/>
</Provider>
);
},

View File

@ -1,7 +1,8 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import get from 'lodash/get';
import classNames from 'classnames';
import { isValidElement, mergeProps } from '../../_util/props-util';
import { isValidElement } from '../../_util/props-util';
function isInvalidRenderCellText(text) {
return (
@ -11,6 +12,7 @@ function isInvalidRenderCellText(text) {
export default {
name: 'TableCell',
inheritAttrs: false,
props: {
record: PropTypes.object,
prefixCls: PropTypes.string,
@ -21,8 +23,10 @@ export default {
expandIcon: PropTypes.any,
component: PropTypes.any,
},
inject: {
table: { default: () => ({}) },
setup() {
return {
table: inject('table', {}),
};
},
methods: {
handleClick(e) {
@ -60,11 +64,7 @@ export default {
text = get(record, dataIndex);
}
let tdProps = {
props: {},
attrs: {},
on: {
click: this.handleClick,
},
onClick: this.handleClick,
};
let colSpan;
let rowSpan;
@ -72,18 +72,14 @@ export default {
if (customRender) {
text = customRender(text, record, index, column);
if (isInvalidRenderCellText(text)) {
tdProps.attrs = text.attrs || {};
tdProps.props = text.props || {};
tdProps.class = text.class;
tdProps.style = text.style;
colSpan = tdProps.attrs.colSpan;
rowSpan = tdProps.attrs.rowSpan;
tdProps = text.props || tdProps;
({ colSpan, rowSpan } = tdProps);
text = text.children;
}
}
if (column.customCell) {
tdProps = mergeProps(tdProps, column.customCell(record, index));
tdProps = { ...tdProps, ...column.customCell(record, index) };
}
// Fix https://github.com/ant-design/ant-design/issues/1202
@ -118,7 +114,7 @@ export default {
if (column.ellipsis) {
if (typeof text === 'string') {
tdProps.attrs.title = text;
tdProps.title = text;
} else if (text) {
// const { props: textProps } = text;
// if (textProps && textProps.children && typeof textProps.children === 'string') {

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import TableHeaderRow from './TableHeaderRow';
@ -42,13 +43,16 @@ function getHeaderRows({ columns = [], currentRow = 0, rows = [], isLast = true
export default {
name: 'TableHeader',
inheritAttrs: false,
props: {
fixed: PropTypes.string,
columns: PropTypes.array.isRequired,
expander: PropTypes.object.isRequired,
},
inject: {
table: { default: () => ({}) },
setup() {
return {
table: inject('table', {}),
};
},
render() {

View File

@ -1,9 +1,10 @@
import classNames from 'classnames';
import PropTypes from '../../_util/vue-types';
import { connect } from '../../_util/store';
import { mergeProps } from '../../_util/props-util';
const TableHeaderRow = {
name: 'TableHeaderRow',
inheritAttrs: false,
props: {
index: PropTypes.number,
fixed: PropTypes.string,
@ -15,8 +16,7 @@ const TableHeaderRow = {
customHeaderRow: PropTypes.func,
prefixCls: PropTypes.prefixCls,
},
name: 'TableHeaderRow',
render(h) {
render() {
const { row, index, height, components, customHeaderRow, prefixCls } = this;
const HeaderRow = components.header.row;
const HeaderCell = components.header.cell;
@ -34,17 +34,11 @@ const TableHeaderRow = {
{row.map((cell, i) => {
const { column, isLast, children, className, ...cellProps } = cell;
const customProps = column.customHeaderCell ? column.customHeaderCell(column) : {};
const headerCellProps = mergeProps(
{
attrs: {
...cellProps,
},
},
{
...customProps,
key: column.key || column.dataIndex || i,
},
);
const headerCellProps = {
...cellProps,
...customProps,
key: column.key || column.dataIndex || i,
};
if (column.align) {
headerCellProps.style = { ...customProps.style, textAlign: column.align };
@ -64,7 +58,7 @@ const TableHeaderRow = {
);
if (typeof HeaderCell === 'function') {
return HeaderCell(h, headerCellProps, children);
return HeaderCell(headerCellProps, children);
}
return <HeaderCell {...headerCellProps}>{children}</HeaderCell>;
})}

View File

@ -2,12 +2,13 @@ import classNames from 'classnames';
import PropTypes from '../../_util/vue-types';
import { connect } from '../../_util/store';
import TableCell from './TableCell';
import { initDefaultProps, mergeProps, getStyle } from '../../_util/props-util';
import { initDefaultProps, findDOMNode } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
import warning from '../../_util/warning';
function noop() {}
const TableRow = {
name: 'TableRow',
inheritAttrs: false,
mixins: [BaseMixin],
props: initDefaultProps(
{
@ -140,7 +141,7 @@ const TableRow = {
getStyle() {
const { height, visible } = this;
let style = getStyle(this);
let style = this.$attrs.style || {};
if (height) {
style = { ...style, height };
}
@ -153,7 +154,7 @@ const TableRow = {
},
saveRowRef() {
this.rowRef = this.$el;
this.rowRef = findDOMNode(this);
const { isAnyColumnsFixed, fixed, expandedRow, ancestorKeys } = this;
@ -196,7 +197,7 @@ const TableRow = {
const BodyRow = components.body.row;
const BodyCell = components.body.cell;
let className = '';
let className = this.$attrs.class || '';
if (hovered) {
className += ` ${prefixCls}-hover`;
@ -246,35 +247,27 @@ const TableRow = {
customClassName,
customClass,
);
const rowPropEvents = rowProps.on || {};
const bodyRowProps = mergeProps(
{ ...rowProps, style },
{
on: {
click: e => {
this.onRowClick(e, rowPropEvents.click);
},
dblclick: e => {
this.onRowDoubleClick(e, rowPropEvents.dblclick);
},
mouseenter: e => {
this.onMouseEnter(e, rowPropEvents.mouseenter);
},
mouseleave: e => {
this.onMouseLeave(e, rowPropEvents.mouseleave);
},
contextmenu: e => {
this.onContextMenu(e, rowPropEvents.contextmenu);
},
},
class: rowClassName,
const bodyRowProps = {
...rowProps,
style,
onClick: e => {
this.onRowClick(e, rowProps.click);
},
{
attrs: {
'data-row-key': rowKey,
},
onDblclick: e => {
this.onRowDoubleClick(e, rowProps.dblclick);
},
);
onMouseenter: e => {
this.onMouseEnter(e, rowProps.mouseenter);
},
onMouseleave: e => {
this.onMouseLeave(e, rowProps.mouseleave);
},
onContextmenu: e => {
this.onContextMenu(e, rowProps.contextmenu);
},
class: rowClassName,
'data-row-key': rowKey,
};
return <BodyRow {...bodyRowProps}>{cells}</BodyRow>;
},
};

View File

@ -85,3 +85,16 @@ export function remove(array, item) {
const last = array.slice(index + 1, array.length);
return front.concat(last);
}
/**
* Returns only data- and aria- key/value pairs
* @param {object} props
*/
export function getDataAndAriaProps(props) {
return Object.keys(props).reduce((memo, key) => {
if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-') {
memo[key] = props[key];
}
return memo;
}, {});
}