shineout
Version:
Shein 前端组件库
334 lines (289 loc) • 11.8 kB
JavaScript
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;