From ee6cec5a2d1781907f6c258ce923e590e09bb69a Mon Sep 17 00:00:00 2001 From: AllenFang Date: Mon, 17 Sep 2018 23:12:16 +0800 Subject: [PATCH] refactoring row level components --- .../src/row-aggregator.js | 143 ----------------- .../src/row-selection/row-binder.js | 57 ------- .../selection-header-cell-binder.js | 8 - packages/react-bootstrap-table2/src/row.js | 146 ------------------ .../src/row/aggregate-row.js | 110 +++++++++++++ .../src/row/event-delegater.js | 78 ++++++++++ .../src/row/row-pure-content.js | 110 +++++++++++++ .../src/{ => row}/row-section.js | 0 .../should-updater.js} | 14 +- .../src/row/simple-row.js | 56 +++++++ 10 files changed, 364 insertions(+), 358 deletions(-) delete mode 100644 packages/react-bootstrap-table2/src/row-aggregator.js delete mode 100644 packages/react-bootstrap-table2/src/row-selection/row-binder.js delete mode 100644 packages/react-bootstrap-table2/src/row-selection/selection-header-cell-binder.js delete mode 100644 packages/react-bootstrap-table2/src/row.js create mode 100644 packages/react-bootstrap-table2/src/row/aggregate-row.js create mode 100644 packages/react-bootstrap-table2/src/row/event-delegater.js create mode 100644 packages/react-bootstrap-table2/src/row/row-pure-content.js rename packages/react-bootstrap-table2/src/{ => row}/row-section.js (100%) rename packages/react-bootstrap-table2/src/{row-should-updater.js => row/should-updater.js} (72%) create mode 100644 packages/react-bootstrap-table2/src/row/simple-row.js diff --git a/packages/react-bootstrap-table2/src/row-aggregator.js b/packages/react-bootstrap-table2/src/row-aggregator.js deleted file mode 100644 index f9438b3..0000000 --- a/packages/react-bootstrap-table2/src/row-aggregator.js +++ /dev/null @@ -1,143 +0,0 @@ -/* eslint react/prop-types: 0 */ -/* eslint react/no-array-index-key: 0 */ -import React from 'react'; -import PropTypes from 'prop-types'; -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 shouldRowUpdater(React.Component) { - static propTypes = { - attrs: PropTypes.object - } - static defaultProps = { - attrs: {} - } - - constructor(props) { - super(props); - this.clickNum = 0; - 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 { - row, - selected, - keyField, - selectable, - expandable, - rowIndex, - expanded, - expandRow, - selectRow, - DELAY_FOR_DBCLICK - } = this.props; - - const clickFn = () => { - if (cb) { - cb(e, row, rowIndex); - } - const key = _.get(row, keyField); - if (expandRow && expandable) { - expandRow.onRowExpand(key, !expanded, rowIndex, e); - } - if (selectRow.clickToSelect && selectable) { - selectRow.onRowSelect(key, !selected, rowIndex, e); - } - }; - - if (DELAY_FOR_DBCLICK) { - this.clickNum += 1; - _.debounce(() => { - if (this.clickNum === 1) { - clickFn(); - } - this.clickNum = 0; - }, DELAY_FOR_DBCLICK)(); - } else { - clickFn(); - } - }; - } - - render() { - const { - row, - columns, - keyField, - rowIndex, - style, - className, - attrs, - selectRow, - expandRow, - expanded, - selected, - selectable, - ...rest - } = this.props; - - const key = _.get(row, keyField); - const { hideSelectColumn, clickToSelect } = selectRow; - const { showExpandColumn } = expandRow; - - const newAttrs = { ...attrs }; - if (clickToSelect || !!expandRow.renderer) { - newAttrs.onClick = this.createClickEventHandler(attrs.onClick); - } - - return ( - - { - showExpandColumn ? ( - - ) : null - } - { - !hideSelectColumn - ? ( - - ) - : null - } - - ); - } -} diff --git a/packages/react-bootstrap-table2/src/row-selection/row-binder.js b/packages/react-bootstrap-table2/src/row-selection/row-binder.js deleted file mode 100644 index 27982a0..0000000 --- a/packages/react-bootstrap-table2/src/row-selection/row-binder.js +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint react/prop-types: 0 */ -import React from 'react'; -import cs from 'classnames'; -import _ from '../utils'; -import SelectionContext from '../contexts/selection-context'; - -export default (Component) => { - const renderWithSelection = (props, selectRow) => { - const key = props.value; - const selected = selectRow.selected.includes(key); - const selectable = !selectRow.nonSelectable || !selectRow.nonSelectable.includes(key); - - let { - style, - className - } = props; - - if (selected) { - const selectedStyle = _.isFunction(selectRow.style) - ? selectRow.style(props.row, props.rowIndex) - : selectRow.style; - - const selectedClasses = _.isFunction(selectRow.classes) - ? selectRow.classes(props.row, props.rowIndex) - : selectRow.classes; - - style = { - ...style, - ...selectedStyle - }; - className = cs(className, selectedClasses) || undefined; - - if (selectRow.bgColor) { - style = style || {}; - style.backgroundColor = _.isFunction(selectRow.bgColor) - ? selectRow.bgColor(props.row, props.rowIndex) - : selectRow.bgColor; - } - } - - return ( - - ); - }; - return props => ( - - { selectRow => renderWithSelection(props, selectRow) } - - ); -}; diff --git a/packages/react-bootstrap-table2/src/row-selection/selection-header-cell-binder.js b/packages/react-bootstrap-table2/src/row-selection/selection-header-cell-binder.js deleted file mode 100644 index de7d3c3..0000000 --- a/packages/react-bootstrap-table2/src/row-selection/selection-header-cell-binder.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import SelectionContext from '../contexts/selection-context'; - -export default Component => () => ( - - { selectRow => } - -); diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js deleted file mode 100644 index f04caed..0000000 --- a/packages/react-bootstrap-table2/src/row.js +++ /dev/null @@ -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 ( - - { 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 ( - - ); - } - // 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 ( - - ); - } - return false; - }) - } - - ); - } -} - -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; diff --git a/packages/react-bootstrap-table2/src/row/aggregate-row.js b/packages/react-bootstrap-table2/src/row/aggregate-row.js new file mode 100644 index 0000000..d176743 --- /dev/null +++ b/packages/react-bootstrap-table2/src/row/aggregate-row.js @@ -0,0 +1,110 @@ +/* eslint react/prop-types: 0 */ +import React from 'react'; +import PropTypes from 'prop-types'; +import _ from '../utils'; +import ExpandCell from '../row-expand/expand-cell'; +import SelectionCell from '../row-selection/selection-cell'; +import shouldUpdater from './should-updater'; +import eventDelegater from './event-delegater'; +import RowPureContent from './row-pure-content'; + +export default class RowAggregator extends shouldUpdater(eventDelegater(React.Component)) { + static propTypes = { + attrs: PropTypes.object, + style: PropTypes.object + } + + static defaultProps = { + attrs: {}, + style: {} + } + + constructor(props) { + super(props); + this.clickNum = 0; + this.shouldUpdateRowContent = false; + this.createClickEventHandler = this.createClickEventHandler.bind(this); + } + + shouldComponentUpdate(nextProps) { + if ( + this.props.selected !== nextProps.selected || + this.props.expanded !== nextProps.expanded || + this.props.selectable !== nextProps.selectable || + this.shouldUpdateByWhenEditing(nextProps) || + this.shouldUpdatedBySelfProps(nextProps) + ) { + this.shouldUpdateRowContent = this.shouldUpdatedByNormalProps(nextProps); + return true; + } + this.shouldUpdateRowContent = this.shouldUpdatedByNormalProps(nextProps); + + return this.shouldUpdateRowContent; + } + + render() { + const { + row, + columns, + keyField, + rowIndex, + style, + className, + attrs, + selectRow, + expandRow, + expanded, + selected, + selectable, + ...rest + } = this.props; + const key = _.get(row, keyField); + const { hideSelectColumn, clickToSelect } = selectRow; + const { showExpandColumn } = expandRow; + + const newAttrs = this.delegate({ ...attrs }); + if (clickToSelect || !!expandRow.renderer) { + newAttrs.onClick = this.createClickEventHandler(newAttrs.onClick); + } + + return ( + + { + showExpandColumn ? ( + + ) : null + } + { + !hideSelectColumn + ? ( + + ) + : null + } + + + ); + } +} diff --git a/packages/react-bootstrap-table2/src/row/event-delegater.js b/packages/react-bootstrap-table2/src/row/event-delegater.js new file mode 100644 index 0000000..2c6868f --- /dev/null +++ b/packages/react-bootstrap-table2/src/row/event-delegater.js @@ -0,0 +1,78 @@ +import _ from '../utils'; + +const events = [ + 'onClick', + 'onDoubleClick', + 'onMouseEnter', + 'onMouseLeave', + 'onContextMenu' +]; + +export default ExtendBase => + class RowEventDelegater extends ExtendBase { + constructor(props) { + super(props); + this.clickNum = 0; + this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this); + this.createClickEventHandler = this.createClickEventHandler.bind(this); + } + + createClickEventHandler(cb) { + return (e) => { + const { + row, + selected, + keyField, + selectable, + expandable, + rowIndex, + expanded, + expandRow, + selectRow, + DELAY_FOR_DBCLICK + } = this.props; + + const clickFn = () => { + if (cb) { + cb(e, row, rowIndex); + } + const key = _.get(row, keyField); + if (expandRow && expandable) { + expandRow.onRowExpand(key, !expanded, rowIndex, e); + } + if (selectRow.clickToSelect && selectable) { + selectRow.onRowSelect(key, !selected, rowIndex, e); + } + }; + + if (DELAY_FOR_DBCLICK) { + this.clickNum += 1; + _.debounce(() => { + if (this.clickNum === 1) { + clickFn(); + } + this.clickNum = 0; + }, DELAY_FOR_DBCLICK)(); + } else { + clickFn(); + } + }; + } + + createDefaultEventHandler(cb) { + return (e) => { + const { row, rowIndex } = this.props; + cb(e, row, rowIndex); + }; + } + + delegate(attrs = {}) { + const newAttrs = { ...attrs }; + Object.keys(attrs).forEach((attr) => { + if (events.includes(attr)) { + newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]); + } + }); + return newAttrs; + } + }; diff --git a/packages/react-bootstrap-table2/src/row/row-pure-content.js b/packages/react-bootstrap-table2/src/row/row-pure-content.js new file mode 100644 index 0000000..52b77f0 --- /dev/null +++ b/packages/react-bootstrap-table2/src/row/row-pure-content.js @@ -0,0 +1,110 @@ +/* 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 RowPureContent extends React.Component { + 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 ( + + ); + } + // 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 ( + + ); + } + return false; + }); + } +} diff --git a/packages/react-bootstrap-table2/src/row-section.js b/packages/react-bootstrap-table2/src/row/row-section.js similarity index 100% rename from packages/react-bootstrap-table2/src/row-section.js rename to packages/react-bootstrap-table2/src/row/row-section.js diff --git a/packages/react-bootstrap-table2/src/row-should-updater.js b/packages/react-bootstrap-table2/src/row/should-updater.js similarity index 72% rename from packages/react-bootstrap-table2/src/row-should-updater.js rename to packages/react-bootstrap-table2/src/row/should-updater.js index 17c9947..294150c 100644 --- a/packages/react-bootstrap-table2/src/row-should-updater.js +++ b/packages/react-bootstrap-table2/src/row/should-updater.js @@ -1,5 +1,5 @@ /* eslint react/prop-types: 0 */ -import _ from './utils'; +import _ from '../utils'; export default ExtendBase => class RowShouldUpdater extends ExtendBase { @@ -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; } diff --git a/packages/react-bootstrap-table2/src/row/simple-row.js b/packages/react-bootstrap-table2/src/row/simple-row.js new file mode 100644 index 0000000..b33e2c6 --- /dev/null +++ b/packages/react-bootstrap-table2/src/row/simple-row.js @@ -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 RowPureContent from './row-pure-content'; +import eventDelegater from './event-delegater'; +import shouldUpdater from './should-updater'; + +class Row extends shouldUpdater(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 ( + + + + ); + } +} + +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;