From 4bc2c5ccd2ddddc8ae9d43c6c0cc9d19b9a15a30 Mon Sep 17 00:00:00 2001
From: tangjinzhou <415800467@qq.com>
Date: Tue, 11 Dec 2018 20:59:23 +0800
Subject: [PATCH] feat: update table
---
components/table/Table.jsx | 157 ++++++++++++++++++----------
components/table/filterDropdown.jsx | 40 ++++++-
components/table/interface.js | 1 +
3 files changed, 138 insertions(+), 60 deletions(-)
diff --git a/components/table/Table.jsx b/components/table/Table.jsx
index dea5f27f4..6b1c89c1d 100755
--- a/components/table/Table.jsx
+++ b/components/table/Table.jsx
@@ -1,6 +1,7 @@
import VcTable from '../vc-table'
import classNames from 'classnames'
+import shallowEqual from 'shallowequal'
import Pagination from '../pagination'
import Icon from '../icon'
import Spin from '../spin'
@@ -308,8 +309,8 @@ export default {
}
},
- getSorterFn () {
- const { sSortOrder: sortOrder, sSortColumn: sortColumn } = this
+ getSorterFn (state) {
+ const { sSortOrder: sortOrder, sSortColumn: sortColumn } = state || this.$data
if (!sortOrder || !sortColumn ||
typeof sortColumn.sorter !== 'function') {
return
@@ -323,25 +324,37 @@ export default {
return 0
}
},
+ isSameColumn (a, b) {
+ if (a && b && a.key && a.key === b.key) {
+ return true
+ }
+ return a === b || shallowEqual(a, b, (value, other) => {
+ if (typeof value === 'function' && typeof other === 'function') {
+ return value === other || value.toString() === other.toString()
+ }
+ })
+ },
toggleSortOrder (order, column) {
- let { sSortOrder: sortOrder, sSortColumn: sortColumn } = this
+ if (!column.sorter) {
+ return
+ }
+ const { sSortOrder: sortOrder, sSortColumn: sortColumn } = this
// 只同时允许一列进行排序,否则会导致排序顺序的逻辑问题
- const isSortColumn = this.isSortColumn(column)
- if (!isSortColumn) { // 当前列未排序
- sortOrder = order
- sortColumn = column
- } else { // 当前列已排序
- if (sortOrder === order) { // 切换为未排序状态
- sortOrder = undefined
- sortColumn = null
- } else { // 切换为排序状态
- sortOrder = order
- }
+ let newSortOrder
+ // 切换另一列时,丢弃 sortOrder 的状态
+ const oldSortOrder = this.isSameColumn(sortColumn, column) ? sortOrder : undefined
+ // 切换排序状态,按照降序/升序/不排序的顺序
+ if (!oldSortOrder) {
+ newSortOrder = 'descend'
+ } else if (oldSortOrder === 'descend') {
+ newSortOrder = 'ascend'
+ } else {
+ newSortOrder = undefined
}
const newState = {
- sSortOrder: sortOrder,
- sSortColumn: sortColumn,
+ sSortOrder: newSortOrder,
+ sSortColumn: newSortOrder ? column : null,
}
// Controlled
@@ -423,7 +436,7 @@ export default {
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection()
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection)
const key = this.getRecordKey(record, rowIndex)
- const pivot = this.$data.pivot
+ const { pivot } = this.$data
const rows = this.getFlatCurrentPageData()
let realIndex = rowIndex
if (this.$props.expandedRowRender) {
@@ -635,7 +648,7 @@ export default {
},
getRecordKey (record, index) {
- const rowKey = this.rowKey
+ const { rowKey } = this
const recordKey = (typeof rowKey === 'function')
? rowKey(record, index) : record[rowKey]
warning(recordKey !== undefined,
@@ -724,11 +737,11 @@ export default {
renderColumnsDropdown (columns, locale) {
const { prefixCls, dropdownPrefixCls } = this
const { sSortOrder: sortOrder } = this
- return treeMap(columns, (originColumn, i) => {
- const column = { ...originColumn }
+ return treeMap(columns, (column, i) => {
const key = this.getColumnKey(column, i)
let filterDropdown
let sortButton
+ const isSortColumn = this.isSortColumn(column)
if ((column.filters && column.filters.length > 0) || column.filterDropdown) {
const colFilters = this.sFilters[key] || []
filterDropdown = (
@@ -741,53 +754,81 @@ export default {
prefixCls={`${prefixCls}-filter`}
dropdownPrefixCls={dropdownPrefixCls || 'ant-dropdown'}
getPopupContainer={this.getPopupContainer}
+ key='filter-dropdown'
/>
)
}
if (column.sorter) {
- const isSortColumn = this.isSortColumn(column)
- if (isSortColumn) {
- column.className = classNames(column.className, {
- [`${prefixCls}-column-sort`]: sortOrder,
- })
- }
+ // const isSortColumn = this.isSortColumn(column)
+ // if (isSortColumn) {
+ // column.className = classNames(column.className, {
+ // [`${prefixCls}-column-sort`]: sortOrder,
+ // })
+ // }
const isAscend = isSortColumn && sortOrder === 'ascend'
const isDescend = isSortColumn && sortOrder === 'descend'
sortButton = (
-
-
+ this.toggleSortOrder('ascend', column)}
- >
-
-
-
+ this.toggleSortOrder('descend', column)}
- >
-
-
+ type='caret-down'
+ theme='filled'
+ />
)
}
- column.title = (
-
- {column.title}
- {sortButton}
- {filterDropdown}
-
- )
-
- if (sortButton || filterDropdown) {
- column.className = classNames(`${prefixCls}-column-has-filters`, column.className)
+ return {
+ ...column,
+ className: classNames(column.className, {
+ [`${prefixCls}-column-has-actions`]: sortButton || filterDropdown,
+ [`${prefixCls}-column-has-filters`]: filterDropdown,
+ [`${prefixCls}-column-has-sorters`]: sortButton,
+ [`${prefixCls}-column-sort`]: isSortColumn && sortOrder,
+ }),
+ title: [
+ this.toggleSortOrder(column)}
+ >
+ {this.renderColumnTitle(column.title)}
+ {sortButton}
+
,
+ filterDropdown,
+ ],
}
+ // column.title = (
+ //
+ // {column.title}
+ // {sortButton}
+ // {filterDropdown}
+ //
+ // )
- return column
+ // if (sortButton || filterDropdown) {
+ // column.className = classNames(`${prefixCls}-column-has-filters`, column.className)
+ // }
+
+ // return column
})
},
-
+ renderColumnTitle (title) {
+ const { sFilters: filters, sSortOrder: sortOrder } = this.$data
+ // https://github.com/ant-design/ant-design/issues/11246#issuecomment-405009167
+ if (title instanceof Function) {
+ return title({
+ filters,
+ sortOrder,
+ })
+ }
+ return title
+ },
handleShowSizeChange (current, pageSize) {
const pagination = this.sPagination
pagination.onShowSizeChange(current, pageSize)
@@ -854,7 +895,11 @@ export default {
sorter.field = state.sSortColumn.dataIndex
sorter.columnKey = this.getColumnKey(state.sSortColumn)
}
- return [pagination, filters, sorter]
+ const extra = {
+ currentDataSource: this.getLocalData(state),
+ }
+
+ return [pagination, filters, sorter, extra]
},
findColumn (myKey) {
@@ -909,12 +954,14 @@ export default {
} : item))
},
- getLocalData () {
- const { dataSource, sFilters: filters } = this
+ getLocalData (state) {
+ const currentState = state || this.$data
+ const { sFilters: filters } = currentState
+ const { dataSource } = this.$props
let data = dataSource || []
// 优化本地排序
data = data.slice(0)
- const sorterFn = this.getSorterFn()
+ const sorterFn = this.getSorterFn(currentState)
if (sorterFn) {
data = this.recursiveSort(data, sorterFn)
}
diff --git a/components/table/filterDropdown.jsx b/components/table/filterDropdown.jsx
index 567660c1d..d7c6bb3aa 100755
--- a/components/table/filterDropdown.jsx
+++ b/components/table/filterDropdown.jsx
@@ -13,6 +13,13 @@ import { initDefaultProps, getOptionProps } from '../_util/props-util'
import { cloneElement } from '../_util/vnode'
import BaseMixin from '../_util/BaseMixin'
+function stopPropagation (e) {
+ e.stopPropagation()
+ if (e.nativeEvent.stopImmediatePropagation) {
+ e.nativeEvent.stopImmediatePropagation()
+ }
+}
+
export default {
mixins: [BaseMixin],
name: 'FilterMenu',
@@ -76,6 +83,9 @@ export default {
// },
},
methods: {
+ getDropdownVisible () {
+ return this.neverShown ? false : this.sVisible
+ },
setNeverShown (column) {
const rootNode = this.$el
const filterBelongToScrollBody = !!closest(rootNode, `.ant-table-scroll`)
@@ -111,6 +121,12 @@ export default {
handleConfirm () {
this.setVisible(false)
this.confirmFilter2()
+ // Call `setSelectedKeys` & `confirm` in the same time will make filter data not up to date
+ // https://github.com/ant-design/ant-design/issues/12284
+ this.$forceUpdate()
+ this.$nextTick(() => {
+ this.confirmFilter
+ })
},
onVisibleChange (visible) {
@@ -188,14 +204,27 @@ export default {
if (typeof filterIcon === 'function') {
filterIcon = filterIcon(filterd)
}
- const dropdownSelectedClass = filterd ? `${prefixCls}-selected` : ''
+ const dropdownIconClass = classNames({
+ [`${prefixCls}-selected`]: filterd,
+ [`${prefixCls}-open`]: this.getDropdownVisible(),
+ })
return filterIcon ? cloneElement(filterIcon, {
attrs: {
title: locale.filterTitle,
},
- class: classNames(`${prefixCls}-icon`, filterIcon.className),
- }) :
+ on: {
+ click: stopPropagation,
+ },
+ class: classNames(`${prefixCls}-icon`, dropdownIconClass, filterIcon.className),
+ })
+ :
},
},
@@ -207,7 +236,7 @@ export default {
[`${dropdownPrefixCls}-menu-without-submenu`]: !this.hasSubMenu(),
})
let { filterDropdown } = column
- if (filterDropdown && typeof filterDropdown === 'function') {
+ if (filterDropdown instanceof Function) {
filterDropdown = filterDropdown({
prefixCls: `${dropdownPrefixCls}-custom`,
setSelectedKeys: (selectedKeys) => this.setSelectedKeys({ selectedKeys }),
@@ -257,7 +286,8 @@ export default {
return (