UNPKG

element-ui

Version:

A Component Library for Vue.js.

382 lines (333 loc) 11.5 kB
import Vue from 'vue'; import merge from 'element-ui/src/utils/merge'; import { getKeysMap, getRowIdentity, getColumnById, getColumnByKey, orderBy, toggleRowStatus } from '../util'; import expand from './expand'; import current from './current'; import tree from './tree'; 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, sortingColumn.sortBy); }; const doFlattenColumns = (columns) => { const result = []; columns.forEach((column) => { if (column.children) { result.push.apply(result, doFlattenColumns(column.children)); } else { result.push(column); } }); return result; }; export default Vue.extend({ data() { return { states: { // 3.0 版本后要求必须设置该属性 rowKey: null, // 渲染的数据来源,是对 table 中的 data 过滤排序后的结果 data: [], // 是否包含固定列 isComplex: false, // 列 _columns: [], // 不可响应的 originColumns: [], columns: [], fixedColumns: [], rightFixedColumns: [], leafColumns: [], fixedLeafColumns: [], rightFixedLeafColumns: [], leafColumnsLength: 0, fixedLeafColumnsLength: 0, rightFixedLeafColumnsLength: 0, // 选择 isAllSelected: false, selection: [], reserveSelection: false, selectOnIndeterminate: false, selectable: null, // 过滤 filters: {}, // 不可响应的 filteredData: null, // 排序 sortingColumn: null, sortProp: null, sortOrder: null, hoverRow: null } }; }, mixins: [expand, current, tree], methods: { // 检查 rowKey 是否存在 assertRowKey() { const rowKey = this.states.rowKey; if (!rowKey) throw new Error('[ElTable] prop row-key is required'); }, // 更新列 updateColumns() { const states = this.states; const _columns = states._columns || []; states.fixedColumns = _columns.filter((column) => column.fixed === true || column.fixed === 'left'); states.rightFixedColumns = _columns.filter((column) => column.fixed === 'right'); if (states.fixedColumns.length > 0 && _columns[0] && _columns[0].type === 'selection' && !_columns[0].fixed) { _columns[0].fixed = true; states.fixedColumns.unshift(_columns[0]); } const notFixedColumns = _columns.filter(column => !column.fixed); states.originColumns = [].concat(states.fixedColumns).concat(notFixedColumns).concat(states.rightFixedColumns); const leafColumns = doFlattenColumns(notFixedColumns); const fixedLeafColumns = doFlattenColumns(states.fixedColumns); const rightFixedLeafColumns = doFlattenColumns(states.rightFixedColumns); states.leafColumnsLength = leafColumns.length; states.fixedLeafColumnsLength = fixedLeafColumns.length; states.rightFixedLeafColumnsLength = rightFixedLeafColumns.length; states.columns = [].concat(fixedLeafColumns).concat(leafColumns).concat(rightFixedLeafColumns); states.isComplex = states.fixedColumns.length > 0 || states.rightFixedColumns.length > 0; }, // 更新 DOM scheduleLayout(needUpdateColumns) { if (needUpdateColumns) { this.updateColumns(); } this.table.debouncedUpdateLayout(); }, // 选择 isSelected(row) { const { selection = [] } = this.states; return selection.indexOf(row) > -1; }, clearSelection() { const states = this.states; states.isAllSelected = false; const oldSelection = states.selection; if (oldSelection.length) { states.selection = []; this.table.$emit('selection-change', []); } }, cleanSelection() { const states = this.states; const { data, rowKey, selection } = states; let deleted; if (rowKey) { deleted = []; const selectedMap = getKeysMap(selection, rowKey); const dataMap = getKeysMap(data, rowKey); for (let key in selectedMap) { if (selectedMap.hasOwnProperty(key) && !dataMap[key]) { deleted.push(selectedMap[key].row); } } } else { deleted = selection.filter(item => data.indexOf(item) === -1); } if (deleted.length) { const newSelection = selection.filter(item => deleted.indexOf(item) === -1); states.selection = newSelection; this.table.$emit('selection-change', newSelection.slice()); } }, toggleRowSelection(row, selected, emitChange = true) { const changed = toggleRowStatus(this.states.selection, row, selected); if (changed) { const newSelection = (this.states.selection || []).slice(); // 调用 API 修改选中值,不触发 select 事件 if (emitChange) { this.table.$emit('select', newSelection, row); } this.table.$emit('selection-change', newSelection); } }, _toggleAllSelection() { const states = this.states; const { data = [], selection } = states; // when only some rows are selected (but not all), select or deselect all of them // depending on the value of selectOnIndeterminate const value = states.selectOnIndeterminate ? !states.isAllSelected : !(states.isAllSelected || selection.length); states.isAllSelected = value; let selectionChanged = false; data.forEach((row, index) => { if (states.selectable) { if (states.selectable.call(null, row, index) && toggleRowStatus(selection, row, value)) { selectionChanged = true; } } else { if (toggleRowStatus(selection, row, value)) { selectionChanged = true; } } }); if (selectionChanged) { this.table.$emit('selection-change', selection ? selection.slice() : []); } this.table.$emit('select-all', selection); }, updateSelectionByRowKey() { const states = this.states; const { selection, rowKey, data } = states; const selectedMap = getKeysMap(selection, rowKey); data.forEach(row => { const rowId = getRowIdentity(row, rowKey); const rowInfo = selectedMap[rowId]; if (rowInfo) { selection[rowInfo.index] = row; } }); }, updateAllSelected() { const states = this.states; const { selection, rowKey, selectable } = states; // data 为 null 时,解构时的默认值会被忽略 const data = states.data || []; if (data.length === 0) { states.isAllSelected = false; return; } let selectedMap; if (rowKey) { selectedMap = getKeysMap(selection, rowKey); } const isSelected = function(row) { if (selectedMap) { return !!selectedMap[getRowIdentity(row, rowKey)]; } else { return selection.indexOf(row) !== -1; } }; let isAllSelected = true; let selectedCount = 0; for (let i = 0, j = data.length; i < j; i++) { const item = data[i]; const isRowSelectable = selectable && selectable.call(null, item, i); if (!isSelected(item)) { if (!selectable || isRowSelectable) { isAllSelected = false; break; } } else { selectedCount++; } } if (selectedCount === 0) isAllSelected = false; states.isAllSelected = isAllSelected; }, // 过滤与排序 updateFilters(columns, values) { if (!Array.isArray(columns)) { columns = [columns]; } const states = this.states; const filters = {}; columns.forEach(col => { states.filters[col.id] = values; filters[col.columnKey || col.id] = values; }); return filters; }, updateSort(column, prop, order) { if (this.states.sortingColumn && this.states.sortingColumn !== column) { this.states.sortingColumn.order = null; } this.states.sortingColumn = column; this.states.sortProp = prop; this.states.sortOrder = order; }, execFilter() { const states = this.states; const { _data, filters } = states; let data = _data; Object.keys(filters).forEach((columnId) => { const values = states.filters[columnId]; if (!values || values.length === 0) return; const column = getColumnById(this.states, columnId); if (column && column.filterMethod) { data = data.filter((row) => { return values.some(value => column.filterMethod.call(null, value, row, column)); }); } }); states.filteredData = data; }, execSort() { const states = this.states; states.data = sortData(states.filteredData, states); }, // 根据 filters 与 sort 去过滤 data execQuery(ignore) { if (!(ignore && ignore.filter)) { this.execFilter(); } this.execSort(); }, clearFilter(columnKeys) { const states = this.states; const { tableHeader, fixedTableHeader, rightFixedTableHeader } = this.table.$refs; let panels = {}; if (tableHeader) panels = merge(panels, tableHeader.filterPanels); if (fixedTableHeader) panels = merge(panels, fixedTableHeader.filterPanels); if (rightFixedTableHeader) panels = merge(panels, rightFixedTableHeader.filterPanels); const keys = Object.keys(panels); if (!keys.length) return; if (typeof columnKeys === 'string') { columnKeys = [columnKeys]; } if (Array.isArray(columnKeys)) { const columns = columnKeys.map(key => getColumnByKey(states, key)); keys.forEach(key => { const column = columns.find(col => col.id === key); if (column) { // TODO: 优化这里的代码 panels[key].filteredValue = []; } }); this.commit('filterChange', { column: columns, values: [], silent: true, multi: true }); } else { keys.forEach(key => { // TODO: 优化这里的代码 panels[key].filteredValue = []; }); states.filters = {}; this.commit('filterChange', { column: {}, values: [], silent: true }); } }, clearSort() { const states = this.states; if (!states.sortingColumn) return; this.updateSort(null, null, null); this.commit('changeSortCondition', { silent: true }); }, // 适配层,expand-row-keys 在 Expand 与 TreeTable 中都有使用 setExpandRowKeysAdapter(val) { // 这里会触发额外的计算,但为了兼容性,暂时这么做 this.setExpandRowKeys(val); this.updateTreeExpandKeys(val); }, // 展开行与 TreeTable 都要使用 toggleRowExpansionAdapter(row, expanded) { const hasExpandColumn = this.states.columns.some(({ type }) => type === 'expand'); if (hasExpandColumn) { this.toggleRowExpansion(row, expanded); } else { this.toggleTreeExpansion(row, expanded); } } } });