Эх сурвалжийг харах

Merge pull request #691 from furybean/table-remote-sort

Table: add column remote/custom sort.
杨奕 8 жил өмнө
parent
commit
8e60aff175

+ 3 - 1
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) | — | — |

+ 6 - 13
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 <div>{ $index + 1 }</div>;
     },
     sortable: false
-  },
-  filter: {
-    headerTemplate: function(h) {
-      return '#';
-    },
-    template: function(h, { row, column }) {
-      return <el-tag type="primary" style="height: 16px; line-height: 16px; min-width: 40px; text-align: center">{ row[column.property] }</el-tag>;
-    },
-    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,

+ 19 - 15
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' : ''] }>
                   <div class={ ['cell', column.filteredValue && column.filteredValue.length > 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');
     }

+ 20 - 8
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());
   },

+ 7 - 2
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;