mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
fix cell level performace, remain select all
This commit is contained in:
parent
c3996f3f47
commit
dffe588f66
@ -1,5 +1,4 @@
|
||||
import createContext from './src/context';
|
||||
import bindCellLevelCellEdit from './src/cell-binder';
|
||||
import bindRowLevelCellEdit from './src/row-binder';
|
||||
import createEditingCell from './src/editing-cell-binder';
|
||||
import {
|
||||
@ -11,7 +10,6 @@ import {
|
||||
export default (options = {}) => ({
|
||||
createContext,
|
||||
createEditingCell,
|
||||
bindCellLevelCellEdit,
|
||||
bindRowLevelCellEdit,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK,
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
|
||||
|
||||
import { Consumer } from './context';
|
||||
|
||||
export default (Component, keyField, _) => {
|
||||
const renderWithCellEdit = (props, cellEdit) => {
|
||||
const content = _.get(props.row, props.column.dataField);
|
||||
const editableRow = props.editable;
|
||||
|
||||
let editable = _.isDefined(props.column.editable) ? props.column.editable : true;
|
||||
if (props.column.dataField === keyField || !editableRow) editable = false;
|
||||
if (_.isFunction(props.column.editable)) {
|
||||
editable = props.column.editable(
|
||||
content,
|
||||
props.row,
|
||||
props.rowIndex,
|
||||
props.columnIndex
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Component
|
||||
{ ...props }
|
||||
onStart={ cellEdit.onStart }
|
||||
editable={ editable }
|
||||
clickToEdit={ cellEdit.mode === CLICK_TO_CELL_EDIT }
|
||||
dbclickToEdit={ cellEdit.mode === DBCLICK_TO_CELL_EDIT }
|
||||
/>
|
||||
);
|
||||
};
|
||||
return props => (
|
||||
<Consumer>
|
||||
{ cellEdit => renderWithCellEdit(props, cellEdit) }
|
||||
</Consumer>
|
||||
);
|
||||
};
|
||||
@ -100,7 +100,6 @@ export default (
|
||||
const {
|
||||
cellEdit: {
|
||||
options: { nonEditableRows, errorMessage, ...optionsRest },
|
||||
createContext,
|
||||
...cellEditRest
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
@ -4,6 +4,7 @@ import { Consumer } from './context';
|
||||
import createEditingCell from './editing-cell';
|
||||
|
||||
export default (_) => {
|
||||
const EditingCell = createEditingCell(_);
|
||||
const renderWithEditingCell = (props, cellEdit) => {
|
||||
const content = _.get(props.row, props.column.dataField);
|
||||
let editCellstyle = props.column.editCellStyle || {};
|
||||
@ -24,7 +25,7 @@ export default (_) => {
|
||||
props.columnIndex)
|
||||
;
|
||||
}
|
||||
const EditingCell = createEditingCell(_);
|
||||
|
||||
return (
|
||||
<EditingCell
|
||||
{ ...props }
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import { DELAY_FOR_DBCLICK, DBCLICK_TO_CELL_EDIT } from './const';
|
||||
import { DELAY_FOR_DBCLICK, DBCLICK_TO_CELL_EDIT, CLICK_TO_CELL_EDIT } from './const';
|
||||
import { Consumer } from './context';
|
||||
|
||||
export default (Component, selectRowEnabled) => {
|
||||
@ -24,6 +24,9 @@ export default (Component, selectRowEnabled) => {
|
||||
editingRowIdx={ cellEdit.ridx }
|
||||
editingColIdx={ cellEdit.cidx }
|
||||
editable={ editableRow }
|
||||
onStart={ cellEdit.onStart }
|
||||
clickToEdit={ cellEdit.mode === CLICK_TO_CELL_EDIT }
|
||||
dbclickToEdit={ cellEdit.mode === DBCLICK_TO_CELL_EDIT }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@ import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator(5000);
|
||||
const products = productsGenerator(5);
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
@ -23,7 +23,6 @@ export default () => (
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ { mode: 'checkbox' } }
|
||||
cellEdit={ cellEditFactory({
|
||||
mode: 'click'
|
||||
}) }
|
||||
|
||||
153
packages/react-bootstrap-table2/src/body.js
vendored
153
packages/react-bootstrap-table2/src/body.js
vendored
@ -6,89 +6,94 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import _ from './utils';
|
||||
import Row from './row';
|
||||
import Cell from './cell';
|
||||
import RowAggregator from './row-aggregator';
|
||||
import RowSection from './row-section';
|
||||
import Const from './const';
|
||||
import bindSelection from './row-selection/row-binder';
|
||||
import bindExpansion from './row-expand/row-binder';
|
||||
|
||||
const Body = (props) => {
|
||||
const {
|
||||
columns,
|
||||
data,
|
||||
keyField,
|
||||
isEmpty,
|
||||
noDataIndication,
|
||||
visibleColumnSize,
|
||||
cellEdit,
|
||||
selectRow,
|
||||
rowStyle,
|
||||
rowClasses,
|
||||
rowEvents,
|
||||
expandRow
|
||||
} = props;
|
||||
|
||||
let content;
|
||||
|
||||
if (isEmpty) {
|
||||
const indication = _.isFunction(noDataIndication) ? noDataIndication() : noDataIndication;
|
||||
if (!indication) {
|
||||
return null;
|
||||
class Body extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
if (props.cellEdit.createContext) {
|
||||
this.EditingCell = props.cellEdit.createEditingCell(_, props.cellEdit.options.onStartEdit);
|
||||
}
|
||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||
} else {
|
||||
let RowComponent = Row;
|
||||
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||
const expandRowEnabled = !!expandRow.renderer;
|
||||
|
||||
const additionalRowProps = {};
|
||||
if (expandRowEnabled) {
|
||||
RowComponent = bindExpansion(RowAggregator, visibleColumnSize);
|
||||
}
|
||||
|
||||
if (selectRowEnabled) {
|
||||
RowComponent = bindSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||
}
|
||||
|
||||
if (cellEdit.createContext) {
|
||||
const CellComponent = cellEdit.bindCellLevelCellEdit(Cell, keyField, _);
|
||||
const EditingCell = cellEdit.createEditingCell(_, cellEdit.options.onStartEdit);
|
||||
RowComponent = cellEdit.bindRowLevelCellEdit(RowComponent, selectRowEnabled);
|
||||
additionalRowProps.CellComponent = CellComponent;
|
||||
additionalRowProps.EditingCellComponent = EditingCell;
|
||||
}
|
||||
|
||||
if (selectRowEnabled || expandRowEnabled) {
|
||||
additionalRowProps.expandRow = expandRow;
|
||||
additionalRowProps.selectRow = selectRow;
|
||||
}
|
||||
|
||||
content = data.map((row, index) => {
|
||||
const key = _.get(row, keyField);
|
||||
const baseRowProps = {
|
||||
key,
|
||||
row,
|
||||
columns,
|
||||
keyField,
|
||||
cellEdit,
|
||||
value: key,
|
||||
rowIndex: index,
|
||||
attrs: rowEvents || {},
|
||||
...additionalRowProps
|
||||
};
|
||||
|
||||
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
||||
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
||||
|
||||
return <RowComponent { ...baseRowProps } />;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<tbody>{ content }</tbody>
|
||||
);
|
||||
};
|
||||
render() {
|
||||
const {
|
||||
columns,
|
||||
data,
|
||||
keyField,
|
||||
isEmpty,
|
||||
noDataIndication,
|
||||
visibleColumnSize,
|
||||
cellEdit,
|
||||
selectRow,
|
||||
rowStyle,
|
||||
rowClasses,
|
||||
rowEvents,
|
||||
expandRow
|
||||
} = this.props;
|
||||
|
||||
let content;
|
||||
|
||||
if (isEmpty) {
|
||||
const indication = _.isFunction(noDataIndication) ? noDataIndication() : noDataIndication;
|
||||
if (!indication) {
|
||||
return null;
|
||||
}
|
||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||
} else {
|
||||
let RowComponent = Row;
|
||||
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||
const expandRowEnabled = !!expandRow.renderer;
|
||||
|
||||
const additionalRowProps = {};
|
||||
if (expandRowEnabled) {
|
||||
RowComponent = bindExpansion(RowAggregator, visibleColumnSize);
|
||||
}
|
||||
|
||||
if (selectRowEnabled) {
|
||||
RowComponent = bindSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||
}
|
||||
|
||||
if (cellEdit.createContext) {
|
||||
RowComponent = cellEdit.bindRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
||||
additionalRowProps.EditingCellComponent = this.EditingCell;
|
||||
}
|
||||
|
||||
if (selectRowEnabled || expandRowEnabled) {
|
||||
additionalRowProps.expandRow = expandRow;
|
||||
additionalRowProps.selectRow = selectRow;
|
||||
}
|
||||
|
||||
content = data.map((row, index) => {
|
||||
const key = _.get(row, keyField);
|
||||
const baseRowProps = {
|
||||
key,
|
||||
row,
|
||||
columns,
|
||||
keyField,
|
||||
cellEdit,
|
||||
value: key,
|
||||
rowIndex: index,
|
||||
attrs: rowEvents || {},
|
||||
...additionalRowProps
|
||||
};
|
||||
|
||||
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
||||
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
||||
|
||||
return <RowComponent { ...baseRowProps } />;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<tbody>{ content }</tbody>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Body.propTypes = {
|
||||
keyField: PropTypes.string.isRequired,
|
||||
|
||||
@ -6,8 +6,9 @@ import _ from './utils';
|
||||
import Row from './row';
|
||||
import ExpandCell from './row-expand/expand-cell';
|
||||
import SelectionCell from './row-selection/selection-cell';
|
||||
import shouldRowUpdater from './row-should-updater';
|
||||
|
||||
export default class RowAggregator extends React.Component {
|
||||
export default class RowAggregator extends shouldRowUpdater(React.Component) {
|
||||
static propTypes = {
|
||||
attrs: PropTypes.object
|
||||
}
|
||||
@ -21,6 +22,17 @@ export default class RowAggregator extends React.Component {
|
||||
this.createClickEventHandler = this.createClickEventHandler.bind(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const shouldUpdate =
|
||||
this.props.selected !== nextProps.selected ||
|
||||
this.props.expanded !== nextProps.expanded ||
|
||||
this.props.selectable !== nextProps.selectable ||
|
||||
this.shouldUpdateByWhenEditing(nextProps) ||
|
||||
this.shouldUpdatedByNormalProps(nextProps);
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
createClickEventHandler(cb) {
|
||||
return (e) => {
|
||||
const {
|
||||
@ -91,6 +103,7 @@ export default class RowAggregator extends React.Component {
|
||||
|
||||
return (
|
||||
<Row
|
||||
shouldUpdate
|
||||
key={ key }
|
||||
row={ row }
|
||||
keyField={ keyField }
|
||||
|
||||
@ -28,7 +28,7 @@ export default (Component) => {
|
||||
...style,
|
||||
...selectedStyle
|
||||
};
|
||||
className = cs(className, selectedClasses);
|
||||
className = cs(className, selectedClasses) || undefined;
|
||||
|
||||
if (selectRow.bgColor) {
|
||||
style = style || {};
|
||||
|
||||
@ -25,9 +25,13 @@ export default class SelectionCell extends Component {
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const { selected } = this.props;
|
||||
const shouldUpdate =
|
||||
this.props.rowIndex !== nextProps.rowIndex ||
|
||||
this.props.selected !== nextProps.selected ||
|
||||
this.props.disabled !== nextProps.disabled ||
|
||||
this.props.rowKey !== nextProps.rowKey;
|
||||
|
||||
return nextProps.selected !== selected;
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
|
||||
25
packages/react-bootstrap-table2/src/row-should-updater.js
vendored
Normal file
25
packages/react-bootstrap-table2/src/row-should-updater.js
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import _ from './utils';
|
||||
|
||||
export default ExtendBase =>
|
||||
class RowShouldUpdater extends ExtendBase {
|
||||
shouldUpdateByWhenEditing(nextProps) {
|
||||
return (
|
||||
nextProps.editingRowIdx === nextProps.rowIndex ||
|
||||
(this.props.editingRowIdx === nextProps.rowIndex &&
|
||||
nextProps.editingRowIdx === null)
|
||||
);
|
||||
}
|
||||
|
||||
shouldUpdatedByNormalProps(nextProps) {
|
||||
const shouldUpdate =
|
||||
this.props.rowIndex !== nextProps.rowIndex ||
|
||||
this.props.className !== nextProps.className ||
|
||||
this.props.editable !== nextProps.editable ||
|
||||
this.props.columns.length !== nextProps.columns.length ||
|
||||
!_.isEqual(this.props.row, nextProps.row) ||
|
||||
!_.isEqual(this.props.style, nextProps.style);
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
};
|
||||
41
packages/react-bootstrap-table2/src/row.js
vendored
41
packages/react-bootstrap-table2/src/row.js
vendored
@ -6,11 +6,23 @@ import PropTypes from 'prop-types';
|
||||
import _ from './utils';
|
||||
import Cell from './cell';
|
||||
import eventDelegater from './row-event-delegater';
|
||||
import shouldRowUpdater from './row-should-updater';
|
||||
|
||||
class Row extends shouldRowUpdater(eventDelegater(Component)) {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
console.log('lol');
|
||||
const shouldUpdate =
|
||||
nextProps.shouldUpdate ||
|
||||
this.shouldUpdateByWhenEditing(nextProps) ||
|
||||
this.shouldUpdatedByNormalProps(nextProps);
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
class Row extends eventDelegater(Component) {
|
||||
render() {
|
||||
const {
|
||||
row,
|
||||
keyField,
|
||||
columns,
|
||||
rowIndex,
|
||||
className,
|
||||
@ -18,9 +30,11 @@ class Row extends eventDelegater(Component) {
|
||||
attrs,
|
||||
editable,
|
||||
editingRowIdx,
|
||||
editingColIdx
|
||||
editingColIdx,
|
||||
onStart,
|
||||
clickToEdit,
|
||||
dbclickToEdit
|
||||
} = this.props;
|
||||
const CellComponent = this.props.CellComponent || Cell;
|
||||
const trAttrs = this.delegate(attrs);
|
||||
|
||||
return (
|
||||
@ -35,7 +49,7 @@ class Row extends eventDelegater(Component) {
|
||||
const EditingCell = this.props.EditingCellComponent;
|
||||
return (
|
||||
<EditingCell
|
||||
key={ `${content}-${index}` }
|
||||
key={ `${content}-${index}-editing` }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
column={ column }
|
||||
@ -82,14 +96,23 @@ class Row extends eventDelegater(Component) {
|
||||
if (cellClasses) cellAttrs.className = cellClasses;
|
||||
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||
|
||||
let editableCell = _.isDefined(column.editable) ? column.editable : true;
|
||||
if (column.dataField === keyField || !editable) editableCell = false;
|
||||
if (_.isFunction(column.editable)) {
|
||||
editableCell = column.editable(content, row, rowIndex, index);
|
||||
}
|
||||
|
||||
return (
|
||||
<CellComponent
|
||||
<Cell
|
||||
key={ `${content}-${index}` }
|
||||
row={ row }
|
||||
editable={ editable }
|
||||
editable={ editableCell }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ index }
|
||||
column={ column }
|
||||
onStart={ onStart }
|
||||
clickToEdit={ clickToEdit }
|
||||
dbclickToEdit={ dbclickToEdit }
|
||||
{ ...cellAttrs }
|
||||
/>
|
||||
);
|
||||
@ -108,14 +131,16 @@ Row.propTypes = {
|
||||
columns: PropTypes.array.isRequired,
|
||||
style: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
attrs: PropTypes.object
|
||||
attrs: PropTypes.object,
|
||||
shouldUpdate: PropTypes.bool
|
||||
};
|
||||
|
||||
Row.defaultProps = {
|
||||
editable: true,
|
||||
style: {},
|
||||
className: null,
|
||||
attrs: {}
|
||||
attrs: {},
|
||||
shouldUpdate: false
|
||||
};
|
||||
|
||||
export default Row;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user