diff --git a/CHANGELOG.md b/CHANGELOG.md index 51e7e7fbc..cae55b0a9 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/examples/docs/zh-cn/table.md b/examples/docs/zh-cn/table.md index 21a848996..d7cb83be9 100644 --- a/examples/docs/zh-cn/table.md +++ b/examples/docs/zh-cn/table.md @@ -917,6 +917,7 @@ | 方法名 | 说明 | 参数 | | ---- | ---- | ---- | | clearSelection | 清空用户的选择,当使用 reserve-selection 功能的时候,可能会需要使用此方法 | selection | +| toggleRowSelection | 切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中) | row, selected | ### Table-column Attributes | 参数 | 说明 | 类型 | 可选值 | 默认值 | diff --git a/packages/table/src/table-column.js b/packages/table/src/table-column.js index a8cc50d2a..8982b3bfd 100644 --- a/packages/table/src/table-column.js +++ b/packages/table/src/table-column.js @@ -27,14 +27,13 @@ const forced = { headerTemplate: function(h) { return { this.$emit('allselectedchange', value); } } />; + domProps-value={ this.isAllSelected } />; }, template: function(h, { row, column, store, $index }) { return { row.$selected = value; store.commit('rowSelectedChanged', row); } } />; + on-input={ (value) => { store.commit('rowSelectedChanged', row); } } />; }, sortable: false, resizable: false diff --git a/packages/table/src/table-store.js b/packages/table/src/table-store.js index 9f37d836b..c53f0471f 100644 --- a/packages/table/src/table-store.js +++ b/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; }; diff --git a/packages/table/src/table.vue b/packages/table/src/table.vue index 825903d1d..b08c18053 100644 --- a/packages/table/src/table.vue +++ b/packages/table/src/table.vue @@ -158,6 +158,11 @@ } }; }, + + toggleRowSelection(row, selected) { + this.store.toggleRowSelection(row, selected); + }, + clearSelection() { this.store.clearSelection(); },