diff --git a/examples/docs/zh-cn/table.md b/examples/docs/zh-cn/table.md index a7e222b91..b1f0d2ad6 100644 --- a/examples/docs/zh-cn/table.md +++ b/examples/docs/zh-cn/table.md @@ -918,6 +918,7 @@ | cell-mouse-leave | 当单元格 hover 退出时会触发该事件 | row, column, cell, event | | cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event | | row-click | 当某一行被点击时会触发该事件 | row, event | +| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } | ### Table Methods | 方法名 | 说明 | 参数 | @@ -931,7 +932,8 @@ | prop | 对应列内容的字段名,也可以使用 property 属性 | string | — | — | | width | 对应列的宽度 | string | — | — | | fixed | 列是否固定在左侧或者右侧,true 表示固定在左侧 | string, boolean | true, left, right | - | -| sortable | 对应列是否可以排序 | boolean | — | false | +| sortable | 对应列是否可以排序,如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件 | boolean, string | true, false, 'custom' | false | +| sort-method | 对数据进行排序的时候使用的方法,仅当 sortable 设置为 true 的时候有效 | Function(a, b) | - | - | | resizable | 对应列是否可以通过拖动改变宽度(如果需要在 el-table 上设置 border 属性为真) | boolean | — | true | | type | 对应列的类型。如果设置了 `selection` 则显示多选框,如果设置了 `index` 则显示该行的索引(从 1 开始计算) | string | selection/index | — | | formatter | 用来格式化内容 | Function(row, column) | — | — | diff --git a/packages/table/src/table-column.js b/packages/table/src/table-column.js index 7ebc2792e..a8cc50d2a 100644 --- a/packages/table/src/table-column.js +++ b/packages/table/src/table-column.js @@ -6,19 +6,19 @@ let columnIdSeed = 1; const defaults = { default: { - direction: '' + order: '' }, selection: { width: 48, minWidth: 48, realWidth: 48, - direction: '' + order: '' }, index: { width: 48, minWidth: 48, realWidth: 48, - direction: '' + order: '' } }; @@ -48,15 +48,6 @@ const forced = { return
{ $index + 1 }
; }, sortable: false - }, - filter: { - headerTemplate: function(h) { - return '#'; - }, - template: function(h, { row, column }) { - return { row[column.property] }; - }, - resizable: false } }; @@ -98,9 +89,10 @@ export default { minWidth: {}, template: String, sortable: { - type: Boolean, + type: [Boolean, String], default: false }, + sortMethod: Function, resizable: { type: Boolean, default: true @@ -201,6 +193,7 @@ export default { isColumnGroup, align: this.align ? 'is-' + this.align : null, sortable: this.sortable, + sortMethod: this.sortMethod, resizable: this.resizable, showTooltipWhenOverflow: this.showTooltipWhenOverflow, formatter: this.formatter, diff --git a/packages/table/src/table-header.js b/packages/table/src/table-header.js index d827de61e..f89b831be 100644 --- a/packages/table/src/table-header.js +++ b/packages/table/src/table-header.js @@ -33,7 +33,7 @@ export default { on-mousemove={ ($event) => this.handleMouseMove($event, column) } on-mouseout={ this.handleMouseOut } on-mousedown={ ($event) => this.handleMouseDown($event, column) } - class={ [column.id, column.direction, column.align, this.isCellHidden(cellIndex) ? 'hidden' : ''] }> + class={ [column.id, column.order, column.align, this.isCellHidden(cellIndex) ? 'hidden' : ''] }>
0 ? 'highlight' : ''] }> { column.headerTemplate @@ -268,26 +268,30 @@ export default { if (!column.sortable) return; - const sortCondition = this.store.states.sortCondition; + const states = this.store.states; + let sortProp = states.sortProp; + let sortOrder; + const sortingColumn = states.sortingColumn; - if (sortCondition.column !== column) { - if (sortCondition.column) { - sortCondition.column.direction = ''; + if (sortingColumn !== column) { + if (sortingColumn) { + sortingColumn.order = null; } - sortCondition.column = column; - sortCondition.property = column.property; + states.sortingColumn = column; + sortProp = column.property; } - if (!column.direction) { - column.direction = 'ascending'; - } else if (column.direction === 'ascending') { - column.direction = 'descending'; + if (!column.order) { + sortOrder = column.order = 'ascending'; + } else if (column.order === 'ascending') { + sortOrder = column.order = 'descending'; } else { - column.direction = ''; - sortCondition.column = null; - sortCondition.property = null; + sortOrder = column.order = null; + states.sortingColumn = null; + sortProp = null; } - sortCondition.direction = column.direction === 'descending' ? -1 : 1; + states.sortProp = sortProp; + states.sortOrder = sortOrder; this.store.commit('changeSortCondition'); } diff --git a/packages/table/src/table-store.js b/packages/table/src/table-store.js index e844b0478..9f37d836b 100644 --- a/packages/table/src/table-store.js +++ b/packages/table/src/table-store.js @@ -11,6 +11,14 @@ const getRowIdentity = (row, rowKey) => { } }; +const sortData = (data, states) => { + const sortingColumn = states.sortingColumn; + if (!sortingColumn || typeof sortingColumn.sortable === 'string') { + return data; + } + return orderBy(data, states.sortProp, states.sortOrder, sortingColumn.sortMethod); +}; + const TableStore = function(table, initialState = {}) { if (!table) { throw new Error('Table is required.'); @@ -26,11 +34,9 @@ const TableStore = function(table, initialState = {}) { _data: null, filteredData: null, data: null, - sortCondition: { - column: null, - property: null, - direction: null - }, + sortingColumn: null, + sortProp: null, + sortOrder: null, isAllSelected: false, selection: [], reserveSelection: false, @@ -52,7 +58,7 @@ TableStore.prototype.mutations = { if (data && data[0] && typeof data[0].$selected === 'undefined') { data.forEach((item) => Vue.set(item, '$selected', false)); } - states.data = orderBy((data || []), states.sortCondition.property, states.sortCondition.direction); + states.data = sortData((data || []), states); if (!states.reserveSelection) { states.isAllSelected = false; @@ -82,7 +88,13 @@ TableStore.prototype.mutations = { }, changeSortCondition(states) { - states.data = orderBy((states.filteredData || states._data || []), states.sortCondition.property, states.sortCondition.direction); + states.data = sortData((states.filteredData || states._data || []), states); + + this.table.$emit('sort-change', { + column: this.states.sortingColumn, + prop: this.states.sortProp, + order: this.states.sortOrder + }); Vue.nextTick(() => this.table.updateScrollY()); }, @@ -113,7 +125,7 @@ TableStore.prototype.mutations = { }); states.filteredData = data; - states.data = orderBy(data, states.sortCondition.property, states.sortCondition.direction); + states.data = sortData(data, states); Vue.nextTick(() => this.table.updateScrollY()); }, diff --git a/packages/table/src/util.js b/packages/table/src/util.js index d7e3e1c2d..b05cd0228 100644 --- a/packages/table/src/util.js +++ b/packages/table/src/util.js @@ -58,14 +58,19 @@ const isObject = function(obj) { return obj !== null && typeof obj === 'object'; }; -export const orderBy = function(array, sortKey, reverse) { +export const orderBy = function(array, sortKey, reverse, sortMethod) { + if (typeof reverse === 'string') { + reverse = reverse === 'descending' ? -1 : 1; + } if (!sortKey) { return array; } const order = (reverse && reverse < 0) ? -1 : 1; // sort on a copy to avoid mutating original array - return array.slice().sort(function(a, b) { + return array.slice().sort(sortMethod ? function(a, b) { + return sortMethod(a, b) ? order : -order; + } : function(a, b) { if (sortKey !== '$key') { if (isObject(a) && '$value' in a) a = a.$value; if (isObject(b) && '$value' in b) b = b.$value;