UNPKG

shineout

Version:

Shein 前端组件库

334 lines (289 loc) 11.8 kB
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; import _extends from "@babel/runtime/helpers/extends"; import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose"; import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import { PureComponent } from '../component'; import { tableClass } from './styles'; import { range, split } from '../utils/numbers'; import Colgroup from './Colgroup'; import Tbody from './Tbody'; import Thead from './Thead'; import Tfoot from './Tfoot'; import { compareColumns } from '../utils/shallowEqual'; import Sticky from '../Sticky'; import { addResizeObserver } from '../utils/dom/element'; function setScrollLeft(target, scrollLeft) { if (target && target.scrollLeft !== scrollLeft) target.scrollLeft = scrollLeft; } var SimpleTable = /*#__PURE__*/ function (_PureComponent) { _inheritsLoose(SimpleTable, _PureComponent); function SimpleTable(props) { var _this; _this = _PureComponent.call(this, props) || this; _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "bindHeader", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "bindBody", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "bindFooter", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "removeReiszeObserver", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "body", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "header", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "footer", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "lastColGroup", void 0); _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "cyclicCounter", void 0); _this.state = { colgroup: undefined, overHeight: false, overWidth: false, resize: false }; _this.handleSortChange = _this.handleSortChange.bind(_assertThisInitialized(_assertThisInitialized(_this))); _this.bindHeader = _this.bindElement.bind(_assertThisInitialized(_assertThisInitialized(_this)), 'header'); _this.bindBody = _this.bindElement.bind(_assertThisInitialized(_assertThisInitialized(_this)), 'body'); _this.bindFooter = _this.bindElement.bind(_assertThisInitialized(_assertThisInitialized(_this)), 'footer'); _this.handleScroll = _this.handleScroll.bind(_assertThisInitialized(_assertThisInitialized(_this))); _this.handleColgroup = _this.handleColgroup.bind(_assertThisInitialized(_assertThisInitialized(_this))); _this.resetColGroup = _this.resetColGroup.bind(_assertThisInitialized(_assertThisInitialized(_this))); // 循环计数器。某些情况[*]下滚动条的出现会导致死循环问题,这里做一个计数器,超过一定次数就不再重置,认定最大 10 次为死循环 // [*] 横向滚动条的出现可能导致竖向滚动条从有到无。此时需要重新计算表头的宽度,否则会出现表头与表格内容不对齐的问题。纵向滚动条消失后,可能导致横向滚动条宽度足够,纵向滚动条再次出现,又导致横向滚动条消失,如此循环。 _this.cyclicCounter = 0; return _this; } var _proto = SimpleTable.prototype; _proto.componentDidMount = function componentDidMount() { this.scrollCheck(); }; _proto.componentDidUpdate = function componentDidUpdate(prevProps) { this.scrollCheck(); var resize = prevProps.data.length === 0 && this.props.data.length; // when resize if (resize && this.body) this.handleScroll({ currentTarget: this.body }); var shouldResetColgroup = this.props.dataChangeResize && this.props.data !== prevProps.data; if (resize || shouldResetColgroup || !compareColumns(prevProps.columns, this.props.columns)) { // eslint-disable-next-line react/no-did-update-set-state this.setState({ colgroup: undefined, resize: true }); } }; _proto.componentWillUnmount = function componentWillUnmount() { if (this.body) this.body.removeEventListener('wheel', this.handleScroll); if (this.removeReiszeObserver) this.removeReiszeObserver(); }; _proto.bindElement = function bindElement(key, el) { this[key] = el; // this.body will be undefined on componentDidMount when columns length is 0 if (key === 'body' && el) { el.addEventListener('wheel', this.handleScroll, { passive: false }); this.removeReiszeObserver = addResizeObserver(el, this.resetColGroup, { direction: 'x' }); } }; _proto.resetColGroup = function resetColGroup() { this.lastColGroup = this.state.colgroup || this.lastColGroup; this.setState({ colgroup: undefined, resize: true }); }; _proto.scrollCheck = function scrollCheck() { var _this2 = this; if (!this.body) return; if (this.cyclicCounter > 10) { this.setState({ overHeight: true }); return; } var overHeight = this.body.scrollHeight > this.body.clientHeight; var overWidth = this.body.scrollWidth > this.body.clientWidth; if (overWidth !== this.state.overWidth) this.setState({ overWidth: overWidth }); if (overHeight !== this.state.overHeight) this.setState({ overHeight: overHeight }); this.cyclicCounter += 1; setTimeout(function () { _this2.cyclicCounter = 0; }); }; _proto.handleSortChange = function handleSortChange(finalOrder, sorter, index, cancelOrder, // 是否是自动触发 manual) { if (this.body) this.body.scrollTop = 0; this.props.onSortChange(finalOrder, sorter, index, cancelOrder, manual); }; _proto.handleColgroup = function handleColgroup(tds) { var columns = this.props.columns; var colgroup = []; var _loop = function _loop(i, count) { var _tds$i$getBoundingCli = tds[i].getBoundingClientRect(), width = _tds$i$getBoundingCli.width; var colSpan = parseInt(tds[i].getAttribute('colspan') || '', 10); if (colSpan > 1) { split(width, range(colSpan).map(function (j) { return columns[i + j].width; })).forEach(function (w) { return colgroup.push(w); }); } else { colgroup.push(width); } }; for (var i = 0, count = tds.length; i < count; i++) { _loop(i, count); } this.setState({ colgroup: colgroup, resize: false }); }; _proto.handleScroll = function handleScroll(_ref) { var currentTarget = _ref.currentTarget; var scrollLeft = currentTarget.scrollLeft; setScrollLeft(this.header, scrollLeft); setScrollLeft(this.body, scrollLeft); setScrollLeft(this.footer, scrollLeft); }; _proto.renderHeader = function renderHeader() { var _this$props = this.props, columns = _this$props.columns, width = _this$props.width, data = _this$props.data, onResize = _this$props.onResize, columnResizable = _this$props.columnResizable, sticky = _this$props.sticky, bordered = _this$props.bordered; var _this$state = this.state, colgroup = _this$state.colgroup, overHeight = _this$state.overHeight; var inner = React.createElement("table", { style: { width: width }, className: tableClass(bordered && 'table-bordered') }, React.createElement(Colgroup, { colgroup: colgroup || this.lastColGroup, columns: columns, resizable: columnResizable }), React.createElement(Thead, _extends({}, this.props, { colgroup: colgroup, onSortChange: this.handleSortChange, onColChange: onResize }))); var empty = data.length === 0; var headerStyle = {}; if (!empty) headerStyle.overflowY = overHeight ? 'scroll' : 'hidden'; var header = React.createElement("div", { key: "head", style: headerStyle, className: tableClass('head', 'simple-head', empty && 'empty-head'), ref: this.bindHeader }, inner); if (sticky) { var stickyProps = Object.assign({ top: 0 }, sticky); return React.createElement(Sticky, _extends({}, stickyProps, { key: "head" }), header); } return header; }; _proto.renderFooter = function renderFooter() { var _this$props2 = this.props, columns = _this$props2.columns, width = _this$props2.width, data = _this$props2.data, columnResizable = _this$props2.columnResizable, bordered = _this$props2.bordered, summary = _this$props2.summary; var _this$state2 = this.state, colgroup = _this$state2.colgroup, overHeight = _this$state2.overHeight, overWidth = _this$state2.overWidth; if (!(data && data.length)) return null; if (!(summary && summary.length)) return null; var inner = React.createElement("table", { style: { width: width }, className: tableClass(bordered && 'table-bordered') }, React.createElement(Colgroup, { colgroup: colgroup || this.lastColGroup, columns: columns, resizable: columnResizable }), React.createElement(Tfoot, this.props)); var footStyle = {}; footStyle.overflowY = overHeight ? 'scroll' : 'hidden'; var footer = React.createElement("div", { key: "foot", style: footStyle, className: tableClass('foot', overWidth && 'foot-scroll-x', 'simple-foot'), ref: this.bindFooter, onScroll: this.handleScroll }, inner); return footer; }; _proto.renderBody = function renderBody() { var _this$props3 = this.props, columns = _this$props3.columns, width = _this$props3.width, fixed = _this$props3.fixed, columnResizable = _this$props3.columnResizable, bordered = _this$props3.bordered, others = _objectWithoutPropertiesLoose(_this$props3, ["columns", "width", "fixed", "columnResizable", "bordered"]); var _this$state3 = this.state, colgroup = _this$state3.colgroup, resize = _this$state3.resize; var minWidthSup = columns.find(function (d) { return d.minWidth; }); return React.createElement("div", { key: "body", className: tableClass('simple-body'), ref: this.bindBody, onScroll: this.handleScroll }, React.createElement("table", { style: { width: width }, className: tableClass(!colgroup && minWidthSup && 'init', bordered && 'table-bordered') }, React.createElement(Colgroup, { colgroup: colgroup, columns: columns, resizable: columnResizable }), React.createElement(Tbody, _extends({ colgroup: colgroup, lazy: false, index: 0, columns: columns, onBodyRender: this.handleColgroup, resize: resize, bordered: bordered, columnResizable: columnResizable }, others)))); }; _proto.render = function render() { var _this$props4 = this.props, columns = _this$props4.columns, width = _this$props4.width, children = _this$props4.children, hideHeader = _this$props4.hideHeader, bordered = _this$props4.bordered; if (!columns || columns.length === 0) return React.createElement("table", { style: { width: width }, className: tableClass(bordered && 'table-bordered') }, children); return [hideHeader ? null : this.renderHeader(), this.renderBody(), this.renderFooter(), children]; }; return SimpleTable; }(PureComponent); export default SimpleTable;