123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- 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);
- }
- }
- }
- });
|