瀏覽代碼

Merge pull request #800 from furybean/table-selection

Table: let table compatible with vuex.
杨奕 8 年之前
父節點
當前提交
855d631f3f
共有 5 個文件被更改,包括 89 次插入56 次删除
  1. 1 1
      CHANGELOG.md
  2. 1 0
      examples/docs/zh-cn/table.md
  3. 3 4
      packages/table/src/table-column.js
  4. 79 51
      packages/table/src/table-store.js
  5. 5 0
      packages/table/src/table.vue

+ 1 - 1
CHANGELOG.md

@@ -45,7 +45,7 @@
 
 - Tabs 组件的 click 和 remove 事件回调参数从 name 改为事件对应的 tab 组件实例
 - 全屏 Loading 现在默认不再锁定屏幕滚动。如果需要的话,可添加 `lock` 修饰符
-- Table 删除属性 fixedColumnCount, customCriteria, customBackgroundColors
+- Table 删除属性 fixedColumnCount、customCriteria、customBackgroundColors、selectionMode
 - Table 的 selectionchange、cellmouseenter、cellmouseleave、cellclick 事件更名为 selection-change、cell-mouse-enter、cell-mouse-leave、cell-click。
 - Pagination 的 currentchange、sizechange 事件更名为 current-change、size-change
 

+ 1 - 0
examples/docs/zh-cn/table.md

@@ -917,6 +917,7 @@
 | 方法名 | 说明 | 参数 |
 | ---- | ---- | ---- |
 | clearSelection | 清空用户的选择,当使用 reserve-selection 功能的时候,可能会需要使用此方法 | selection |
+| toggleRowSelection | 切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中) | row, selected |
 
 ### Table-column Attributes
 | 参数      | 说明          | 类型      | 可选值                           | 默认值  |

+ 3 - 4
packages/table/src/table-column.js

@@ -27,14 +27,13 @@ const forced = {
     headerTemplate: function(h) {
       return <el-checkbox
         nativeOn-click={ this.toggleAllSelection }
-        domProps-value={ this.isAllSelected }
-        on-input={ (value) => { this.$emit('allselectedchange', value); } } />;
+        domProps-value={ this.isAllSelected } />;
     },
     template: function(h, { row, column, store, $index }) {
       return <el-checkbox
-        domProps-value={ row.$selected }
+        domProps-value={ store.isSelected(row) }
         disabled={ column.selectable ? !column.selectable.call(null, row, $index) : false }
-        on-input={ (value) => { row.$selected = value; store.commit('rowSelectedChanged', row); } } />;
+        on-input={ (value) => { store.commit('rowSelectedChanged', row); } } />;
     },
     sortable: false,
     resizable: false

+ 79 - 51
packages/table/src/table-store.js

@@ -19,6 +19,39 @@ const sortData = (data, states) => {
   return orderBy(data, states.sortProp, states.sortOrder, sortingColumn.sortMethod);
 };
 
+const getSelectedMap = function(states, rowKey) {
+  const selectionMap = {};
+  states.selection.forEach((row, index) => {
+    selectionMap[getRowIdentity(row, rowKey)] = { row, index };
+  });
+  return selectionMap;
+};
+
+const toggleRowSelection = function(states, row, selected) {
+  let changed = false;
+  const selection = states.selection;
+  const index = selection.indexOf(row);
+  if (typeof selected === 'undefined') {
+    if (index === -1) {
+      selection.push(row);
+      changed = true;
+    } else {
+      selection.splice(index, 1);
+      changed = true;
+    }
+  } else {
+    if (selected && index === -1) {
+      selection.push(row);
+      changed = true;
+    } else if (!selected && index > -1) {
+      selection.splice(index, 1);
+      changed = true;
+    }
+  }
+
+  return changed;
+};
+
 const TableStore = function(table, initialState = {}) {
   if (!table) {
     throw new Error('Table is required.');
@@ -55,26 +88,21 @@ const TableStore = function(table, initialState = {}) {
 TableStore.prototype.mutations = {
   setData(states, data) {
     states._data = data;
-    if (data && data[0] && typeof data[0].$selected === 'undefined') {
-      data.forEach((item) => Vue.set(item, '$selected', false));
-    }
     states.data = sortData((data || []), states);
+    const selection = states.selection;
 
     if (!states.reserveSelection) {
       states.isAllSelected = false;
     } else {
       const rowKey = states.rowKey;
       if (rowKey) {
-        const selectionMap = {};
-        states.selection.forEach((row) => {
-          selectionMap[getRowIdentity(row, rowKey)] = row;
-        });
+        const selectedMap = getSelectedMap(states, rowKey);
 
         states.data.forEach((row) => {
           const rowId = getRowIdentity(row, rowKey);
-          if (selectionMap[rowId]) {
-            row.$selected = true;
-            selectionMap[rowId] = row;
+          const rowInfo = selectedMap[rowId];
+          if (rowInfo) {
+            selection[rowInfo.index] = row;
           }
         });
 
@@ -159,19 +187,13 @@ TableStore.prototype.mutations = {
   },
 
   rowSelectedChanged(states, row) {
+    const changed = toggleRowSelection(states, row);
     const selection = states.selection;
-    if (row.$selected) {
-      if (selection.indexOf(row) === -1) {
-        selection.push(row);
-      }
-    } else {
-      const index = selection.indexOf(row);
-      if (index > -1) {
-        selection.splice(index, 1);
-      }
+
+    if (changed) {
+      this.table.$emit('selection-change', selection);
+      this.table.$emit('select', selection, row);
     }
-    this.table.$emit('selection-change', selection);
-    this.table.$emit('select', selection, row);
 
     this.updateAllSelected();
   },
@@ -182,30 +204,15 @@ TableStore.prototype.mutations = {
     const selection = this.states.selection;
     let selectionChanged = false;
 
-    const setSelected = (item) => {
-      if (item.$selected !== value) {
-        selectionChanged = true;
-        if (value) {
-          if (selection.indexOf(item) === -1) {
-            selection.push(item);
-          }
-        } else {
-          const itemIndex = selection.indexOf(item);
-          if (itemIndex > -1) {
-            selection.splice(itemIndex, 1);
-          }
-        }
-      }
-      item.$selected = value;
-    };
-
     data.forEach((item, index) => {
       if (states.selectable) {
-        if (states.selectable.call(null, item, index)) {
-          setSelected(item);
+        if (states.selectable.call(null, item, index) && toggleRowSelection(states, item, value)) {
+          selectionChanged = true;
         }
       } else {
-        setSelected(item);
+        if (toggleRowSelection(states, item, value)) {
+          selectionChanged = true;
+        }
       }
     });
 
@@ -230,36 +237,57 @@ TableStore.prototype.updateColumns = function() {
   states.columns = [].concat(states.fixedColumns).concat(_columns.filter((column) => !column.fixed)).concat(states.rightFixedColumns);
 };
 
+TableStore.prototype.isSelected = function(row) {
+  return (this.states.selection || []).indexOf(row) > -1;
+};
+
 TableStore.prototype.clearSelection = function() {
   const states = this.states;
-  const oldSelection = states.selection;
-  oldSelection.forEach((row) => { row.$selected = false; });
-  if (this.states.reserveSelection) {
-    const data = states.data || [];
-    data.forEach((row) => { row.$selected = false; });
-  }
   states.isAllSelected = false;
   states.selection = [];
 };
 
+TableStore.prototype.toggleRowSelection = function(row, selected) {
+  toggleRowSelection(this.states, row, selected);
+};
+
 TableStore.prototype.updateAllSelected = function() {
   const states = this.states;
+  const { selection, rowKey, selectable, data } = states;
+  if (!data || data.length === 0) {
+    states.isAllSelected = false;
+    return;
+  }
+
+  let selectedMap;
+  if (rowKey) {
+    selectedMap = getSelectedMap(states, rowKey);
+  }
+
+  const isSelected = function(row) {
+    if (selectedMap) {
+      return !!selectedMap[getRowIdentity(row, rowKey)];
+    } else {
+      return selection.indexOf(row) !== -1;
+    }
+  };
+
   let isAllSelected = true;
-  const data = states.data || [];
   for (let i = 0, j = data.length; i < j; i++) {
     const item = data[i];
-    if (states.selectable) {
-      if (states.selectable.call(null, item, i) && !item.$selected) {
+    if (selectable) {
+      if (selectable.call(null, item, i) && !isSelected(item)) {
         isAllSelected = false;
         break;
       }
     } else {
-      if (!item.$selected) {
+      if (!isSelected(item)) {
         isAllSelected = false;
         break;
       }
     }
   }
+
   states.isAllSelected = isAllSelected;
 };
 

+ 5 - 0
packages/table/src/table.vue

@@ -158,6 +158,11 @@
           }
         };
       },
+
+      toggleRowSelection(row, selected) {
+        this.store.toggleRowSelection(row, selected);
+      },
+
       clearSelection() {
         this.store.clearSelection();
       },