This commit is contained in:
AllenFang 2018-09-16 16:21:39 +08:00
parent 41212fdc55
commit e1986e3e38
11 changed files with 371 additions and 224 deletions

View File

@ -1,10 +1,10 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import cellEditFactory from 'react-bootstrap-table2-editor';
// import cellEditFactory from 'react-bootstrap-table2-editor';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(5);
const products = productsGenerator(2000);
const columns = [{
dataField: 'id',
@ -17,15 +17,41 @@ const columns = [{
text: 'Product Price'
}];
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({
mode: 'click'
}) }
/>
</div>
);
// cellEdit={ cellEditFactory({
// mode: 'click'
// }) }
// const expandRow = {
// renderer: row => (
// <div>
// <p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
// <p>You can render anything here, also you can add additional data on every row object</p>
// <p>expandRow.renderer callback will pass the origin row object to you</p>
// </div>
// )
// };
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
bgColor: 'red'
// selected: [2],
// hideSelectColumn: true
// clickToEdit: true
};
/* eslint react/prefer-stateless-function: 0 */
export default class Table extends React.PureComponent {
render() {
return (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
</div>
);
}
}

View File

@ -5,7 +5,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import _ from './utils';
import Row from './row';
import Row from './simple-row';
import RowAggregator from './row-aggregator';
import RowSection from './row-section';
import Const from './const';
@ -18,6 +18,7 @@ class Body extends React.Component {
if (props.cellEdit.createContext) {
this.EditingCell = props.cellEdit.createEditingCell(_, props.cellEdit.options.onStartEdit);
}
this.RowComponent = bindSelection(RowAggregator);
}
render() {
@ -54,9 +55,9 @@ class Body extends React.Component {
RowComponent = bindExpansion(RowAggregator, visibleColumnSize);
}
if (selectRowEnabled) {
RowComponent = bindSelection(expandRowEnabled ? RowComponent : RowAggregator);
}
// if (selectRowEnabled) {
// RowComponent = bindSelection(expandRowEnabled ? RowComponent : RowAggregator);
// }
if (cellEdit.createContext) {
RowComponent = cellEdit.bindRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
@ -85,7 +86,7 @@ class Body extends React.Component {
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
return <RowComponent { ...baseRowProps } />;
return <this.RowComponent { ...baseRowProps } />;
});
}

View File

@ -73,7 +73,10 @@ class Cell extends Component {
formatExtraData
} = column;
const attrs = { ...rest };
let content = column.isDummyField ? null : _.get(row, dataField);
let content = this.props.children;
if (!content) {
content = column.isDummyField ? null : _.get(row, dataField);
}
if (formatter) {
content = column.formatter(content, row, rowIndex, formatExtraData);

View File

@ -0,0 +1,48 @@
/* eslint react/prop-types: 0 */
/* eslint react/no-array-index-key: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
// import eventDelegater from './row-event-delegater';
import RowContent from './row-pure-content';
// import shouldRowUpdater from './row-should-updater';
/* eslint react/prefer-stateless-function: 0 */
class RowAggregatorContent extends Component {
render() {
const {
className,
style,
attrs,
shouldUpdateRowContent,
...rest
} = this.props;
return (
<tr style={ style } className={ className } { ...attrs }>
{ this.props.children }
<RowContent shouldUpdate={ shouldUpdateRowContent } { ...rest } />
</tr>
);
}
}
RowAggregatorContent.propTypes = {
row: PropTypes.object.isRequired,
rowIndex: PropTypes.number.isRequired,
columns: PropTypes.array.isRequired,
style: PropTypes.object,
className: PropTypes.string,
attrs: PropTypes.object,
shouldUpdateRowContent: PropTypes.bool
};
RowAggregatorContent.defaultProps = {
editable: true,
style: {},
className: null,
attrs: {},
shouldUpdateRowContent: true
};
export default RowAggregatorContent;

View File

@ -3,34 +3,45 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from './utils';
import Row from './row';
import RowContent from './row-pure-content';
// import RowAggregatorContent from './row-aggregator-content';
import shouldRowUpdater from './row-should-updater';
import ExpandCell from './row-expand/expand-cell';
import SelectionCell from './row-selection/selection-cell';
import shouldRowUpdater from './row-should-updater';
// import Cell from './cell';
import eventDelegater from './row-event-delegater';
export default class RowAggregator extends shouldRowUpdater(React.Component) {
export default class RowAggregator extends shouldRowUpdater(eventDelegater(React.Component)) {
static propTypes = {
attrs: PropTypes.object
attrs: PropTypes.object,
style: PropTypes.object
}
static defaultProps = {
attrs: {}
attrs: {},
style: {}
}
constructor(props) {
super(props);
this.clickNum = 0;
this.shouldUpdateRowContent = false;
this.createClickEventHandler = this.createClickEventHandler.bind(this);
}
shouldComponentUpdate(nextProps) {
const shouldUpdate =
if (
this.props.selected !== nextProps.selected ||
this.props.expanded !== nextProps.expanded ||
this.props.selectable !== nextProps.selectable ||
this.shouldUpdateByWhenEditing(nextProps) ||
this.shouldUpdatedByNormalProps(nextProps);
this.shouldUpdatedBySelfProps(nextProps)
) {
this.shouldUpdateRowContent = this.shouldUpdatedByNormalProps(nextProps);
return true;
}
this.shouldUpdateRowContent = this.shouldUpdatedByNormalProps(nextProps);
return shouldUpdate;
return this.shouldUpdateRowContent;
}
createClickEventHandler(cb) {
@ -91,53 +102,77 @@ export default class RowAggregator extends shouldRowUpdater(React.Component) {
selectable,
...rest
} = this.props;
const key = _.get(row, keyField);
const { hideSelectColumn, clickToSelect } = selectRow;
const { showExpandColumn } = expandRow;
const newAttrs = { ...attrs };
const newAttrs = this.delegate({ ...attrs });
if (clickToSelect || !!expandRow.renderer) {
newAttrs.onClick = this.createClickEventHandler(attrs.onClick);
newAttrs.onClick = this.createClickEventHandler(newAttrs.onClick);
}
return (
<Row
shouldUpdate
key={ key }
row={ row }
keyField={ keyField }
rowIndex={ rowIndex }
columns={ columns }
<tr
style={ style }
className={ className }
attrs={ newAttrs }
{ ...rest }
{ ...newAttrs }
>
{
showExpandColumn ? (
<ExpandCell
{ ...expandRow }
rowKey={ key }
rowIndex={ rowIndex }
expanded={ expanded }
/>
) : null
}
{
!hideSelectColumn
? (
<SelectionCell
{ ...selectRow }
rowKey={ key }
rowIndex={ rowIndex }
selected={ selected }
disabled={ !selectable }
/>
)
: null
}
</Row>
<td>123</td>
<td>12121212</td>
</tr>
);
// const content0 = _.get(row, columns[1].dataField);
// const content1 = _.get(row, columns[1].dataField);
// const content2 = _.get(row, columns[2].dataField);
// return (
// <tr
// style={ style }
// className={ className }
// onClick={ e => selectRow.onRowSelect(key, !selected, rowIndex, e) }
// >
// <td>1</td>
// <td>2</td>
// <td>3</td>
// <td>4</td>
// </tr>
// );
// const newCols = [{ fake: true }, ...columns];
// return (
// <tr
// style={ style }
// className={ className }
// { ...newAttrs }
// >
// {
// newCols.map((column, i) => {
// if (column.fake) {
// return (
// <Cell
// key={ `${key}_${i}_sel}` }
// column={ {} }
// row={ {} }
// rowIndex={ rowIndex }
// columnIndex={ i }
// >
// <input type="checkbox" />
// </Cell>
// );
// }
// const content = _.get(row, column.dataField);
// return (
// <Cell
// key={ `${key}_${content}}` }
// row={ row }
// rowIndex={ rowIndex }
// column={ column }
// columnIndex={ i }
// />
// );
// })
// }
// </tr>
// );
}
}

View File

@ -0,0 +1,113 @@
/* eslint react/prop-types: 0 */
/* eslint react/no-array-index-key: 0 */
import React from 'react';
import _ from './utils';
import Cell from './cell';
export default class RowContent extends React.Component {
// shouldComponentUpdate(nextProps) {
// return this.shouldUpdatedByNormalProps(nextProps);
// }
shouldComponentUpdate(nextProps) {
if (typeof this.props.shouldUpdate !== 'undefined') {
if (nextProps.shouldUpdate === this.props.shouldUpdate) {
return false;
}
}
return true;
}
render() {
const {
row,
keyField,
columns,
rowIndex,
editable,
editingRowIdx,
editingColIdx,
onStart,
clickToEdit,
dbclickToEdit,
EditingCellComponent
} = this.props;
return columns.map((column, index) => {
if (!column.hidden) {
const { dataField } = column;
const content = _.get(row, dataField);
if (rowIndex === editingRowIdx && index === editingColIdx) {
return (
<EditingCellComponent
key={ `${content}-${index}-editing` }
row={ row }
rowIndex={ rowIndex }
column={ column }
columnIndex={ index }
/>
);
}
// render cell
let cellTitle;
let cellStyle = {};
const cellAttrs = {
..._.isFunction(column.attrs)
? column.attrs(content, row, rowIndex, index)
: column.attrs,
...column.events
};
const cellClasses = _.isFunction(column.classes)
? column.classes(content, row, rowIndex, index)
: column.classes;
if (column.style) {
cellStyle = _.isFunction(column.style)
? column.style(content, row, rowIndex, index)
: column.style;
cellStyle = Object.assign({}, cellStyle) || {};
}
if (column.title) {
cellTitle = _.isFunction(column.title)
? column.title(content, row, rowIndex, index)
: content;
cellAttrs.title = cellTitle;
}
if (column.align) {
cellStyle.textAlign =
_.isFunction(column.align)
? column.align(content, row, rowIndex, index)
: column.align;
}
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 (
<Cell
key={ `${content}-${index}` }
row={ row }
editable={ editableCell }
rowIndex={ rowIndex }
columnIndex={ index }
column={ column }
onStart={ onStart }
clickToEdit={ clickToEdit }
dbclickToEdit={ dbclickToEdit }
{ ...cellAttrs }
/>
);
}
return false;
});
}
}

View File

@ -43,15 +43,20 @@ export default (Component) => {
{ ...props }
style={ style }
className={ className }
selectRow={ { ...selectRow } }
selectRow={ selectRow }
selected={ selected }
selectable={ selectable }
/>
);
};
return props => (
<SelectionContext.Consumer>
{ selectRow => renderWithSelection(props, selectRow) }
</SelectionContext.Consumer>
);
function withSelectionConsumer(props) {
return (
<SelectionContext.Consumer>
{ selectRow => renderWithSelection(props, selectRow) }
</SelectionContext.Consumer>
);
}
withSelectionConsumer.displayName = 'WithSelectionConsumer';
return withSelectionConsumer;
};

View File

@ -19,17 +19,17 @@ export default class SelectionCell extends Component {
selectionRenderer: PropTypes.func
}
constructor() {
super();
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
shouldComponentUpdate(nextProps) {
const shouldUpdate =
this.props.rowIndex !== nextProps.rowIndex ||
this.props.selected !== nextProps.selected ||
this.props.disabled !== nextProps.disabled ||
this.props.rowKey !== nextProps.rowKey;
this.props.rowKey !== nextProps.rowKey ||
this.props.rowIndex !== nextProps.rowIndex ||
this.props.disabled !== nextProps.disabled;
return shouldUpdate;
}

View File

@ -11,14 +11,20 @@ export default ExtendBase =>
);
}
shouldUpdatedBySelfProps(nextProps) {
return (
this.props.className !== nextProps.className ||
!_.isEqual(this.props.style, nextProps.style) ||
!_.isEqual(this.props.attrs, nextProps.attrs)
);
}
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);
!_.isEqual(this.props.row, nextProps.row);
return shouldUpdate;
}

View File

@ -1,146 +0,0 @@
/* eslint react/prop-types: 0 */
/* eslint react/no-array-index-key: 0 */
import React, { Component } from 'react';
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;
}
render() {
const {
row,
keyField,
columns,
rowIndex,
className,
style,
attrs,
editable,
editingRowIdx,
editingColIdx,
onStart,
clickToEdit,
dbclickToEdit
} = this.props;
const trAttrs = this.delegate(attrs);
return (
<tr style={ style } className={ className } { ...trAttrs }>
{ this.props.children }
{
columns.map((column, index) => {
if (!column.hidden) {
const { dataField } = column;
const content = _.get(row, dataField);
if (rowIndex === editingRowIdx && index === editingColIdx) {
const EditingCell = this.props.EditingCellComponent;
return (
<EditingCell
key={ `${content}-${index}-editing` }
row={ row }
rowIndex={ rowIndex }
column={ column }
columnIndex={ index }
/>
);
}
// render cell
let cellTitle;
let cellStyle = {};
const cellAttrs = {
..._.isFunction(column.attrs)
? column.attrs(content, row, rowIndex, index)
: column.attrs,
...column.events
};
const cellClasses = _.isFunction(column.classes)
? column.classes(content, row, rowIndex, index)
: column.classes;
if (column.style) {
cellStyle = _.isFunction(column.style)
? column.style(content, row, rowIndex, index)
: column.style;
cellStyle = Object.assign({}, cellStyle) || {};
}
if (column.title) {
cellTitle = _.isFunction(column.title)
? column.title(content, row, rowIndex, index)
: content;
cellAttrs.title = cellTitle;
}
if (column.align) {
cellStyle.textAlign =
_.isFunction(column.align)
? column.align(content, row, rowIndex, index)
: column.align;
}
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 (
<Cell
key={ `${content}-${index}` }
row={ row }
editable={ editableCell }
rowIndex={ rowIndex }
columnIndex={ index }
column={ column }
onStart={ onStart }
clickToEdit={ clickToEdit }
dbclickToEdit={ dbclickToEdit }
{ ...cellAttrs }
/>
);
}
return false;
})
}
</tr>
);
}
}
Row.propTypes = {
row: PropTypes.object.isRequired,
rowIndex: PropTypes.number.isRequired,
columns: PropTypes.array.isRequired,
style: PropTypes.object,
className: PropTypes.string,
attrs: PropTypes.object,
shouldUpdate: PropTypes.bool
};
Row.defaultProps = {
editable: true,
style: {},
className: null,
attrs: {},
shouldUpdate: false
};
export default Row;

View File

@ -0,0 +1,56 @@
/* eslint react/prop-types: 0 */
/* eslint react/no-array-index-key: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import eventDelegater from './row-event-delegater';
import RowContent from './row-pure-content';
import shouldRowUpdater from './row-should-updater';
class Row extends shouldRowUpdater(eventDelegater(Component)) {
constructor(props) {
super(props);
this.shouldUpdateRowContent = false;
}
shouldComponentUpdate(nextProps) {
this.shouldUpdateRowContent = this.shouldUpdatedByNormalProps(nextProps);
if (this.shouldUpdateRowContent) return true;
return this.shouldUpdatedBySelfProps(nextProps);
}
render() {
const {
className,
style,
attrs,
...rest
} = this.props;
const trAttrs = this.delegate(attrs);
return (
<tr style={ style } className={ className } { ...trAttrs }>
<RowContent shouldUpdate={ this.shouldUpdateRowContent } { ...rest } />
</tr>
);
}
}
Row.propTypes = {
row: PropTypes.object.isRequired,
rowIndex: PropTypes.number.isRequired,
columns: PropTypes.array.isRequired,
style: PropTypes.object,
className: PropTypes.string,
attrs: PropTypes.object
};
Row.defaultProps = {
editable: true,
style: {},
className: null,
attrs: {}
};
export default Row;