Skip to content

Commit 8348b6a

Browse files
committed
fix(Table): scroll and empty content issues
- scroll in header and body's scrollLeft will change - scroll in lock columns and body's scrollTop will change - when empty, empty content's width will always be the same to the div.next-table
1 parent 361d0a5 commit 8348b6a

File tree

5 files changed

+156
-43
lines changed

5 files changed

+156
-43
lines changed

src/table/fixed.jsx

+67-28
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,19 @@ export default function fixed(BaseComponent) {
4444

4545
static childContextTypes = {
4646
fixedHeader: PropTypes.bool,
47+
getNode: PropTypes.func,
48+
onScroll: PropTypes.func,
4749
maxBodyHeight: PropTypes.oneOfType([
4850
PropTypes.number,
4951
PropTypes.string,
5052
]),
51-
onBodyScroll: PropTypes.func,
52-
getNode: PropTypes.func,
5353
};
5454

5555
getChildContext() {
5656
return {
5757
fixedHeader: this.props.fixedHeader,
5858
maxBodyHeight: this.props.maxBodyHeight,
59-
onBodyScroll: this.onBodyScroll,
59+
onScroll: this.onScroll,
6060
getNode: this.getNode,
6161
};
6262
}
@@ -69,40 +69,70 @@ export default function fixed(BaseComponent) {
6969
this.adjustFixedHeaderSize();
7070
}
7171

72-
adjustFixedHeaderSize() {
73-
const { hasHeader, fixedHeader, rtl } = this.props;
74-
const paddingName = rtl ? 'paddingLeft' : 'paddingRight';
75-
76-
if (hasHeader && fixedHeader && !this.props.lockType) {
77-
if (this.bodyNode.scrollHeight > this.bodyNode.clientHeight) {
78-
dom.setStyle(
79-
this.headerNode,
80-
paddingName,
81-
dom.scrollbar().width
82-
);
83-
} else {
84-
dom.setStyle(this.headerNode, paddingName, 0);
85-
}
86-
}
87-
}
88-
8972
getNode = (type, node, lockType) => {
9073
lockType = lockType
9174
? lockType.charAt(0).toUpperCase() + lockType.substr(1)
9275
: '';
9376
this[`${type}${lockType}Node`] = node;
94-
if (type === 'header' && !lockType) {
95-
this.innerHeaderNode = this.headerNode.querySelector('div');
96-
}
9777
};
9878

99-
onBodyScroll = () => {
100-
this.scrollTo(this.bodyNode.scrollLeft, this.bodyNode.scrollTop);
79+
onScroll = (current = {}) => {
80+
const { onScroll, lockType } = this.props;
81+
onScroll && onScroll(current);
82+
83+
if (lockType || !current.target) {
84+
return;
85+
}
86+
87+
const { scrollLeft, scrollTop } = current.target;
88+
if (current.target === this.bodyNode) {
89+
if (this.bodyNode && scrollTop !== this.bodyNode.scrollTop) {
90+
this.bodyNode.scrollTop = scrollTop;
91+
}
92+
if (
93+
this.headerNode &&
94+
scrollLeft !== this.headerNode.scrollLeft
95+
) {
96+
this.headerNode.scrollLeft = scrollLeft;
97+
}
98+
} else if (current.target === this.headerNode) {
99+
if (this.bodyNode && scrollLeft !== this.bodyNode.scrollLeft) {
100+
this.bodyNode.scrollLeft = scrollLeft;
101+
}
102+
}
101103
};
102104

103-
scrollTo(x) {
104-
if (this.innerHeaderNode) {
105-
this.innerHeaderNode.scrollLeft = x;
105+
adjustFixedHeaderSize() {
106+
const { hasHeader, rtl } = this.props;
107+
const paddingName = rtl ? 'paddingLeft' : 'paddingRight';
108+
const marginName = rtl ? 'marginLeft' : 'marginRight';
109+
const body = this.bodyNode;
110+
111+
if (hasHeader && !this.props.lockType && body) {
112+
const scrollBarSize = dom.scrollbar().width;
113+
const hasVerScroll = body.scrollHeight > body.clientHeight,
114+
hasHozScroll = body.scrollWidth > body.clientWidth;
115+
const style = {
116+
[paddingName]: scrollBarSize,
117+
[marginName]: scrollBarSize,
118+
};
119+
120+
if (!hasVerScroll || !+scrollBarSize) {
121+
style[paddingName] = 0;
122+
style[marginName] = 0;
123+
}
124+
125+
if (+scrollBarSize) {
126+
style.marginBottom = -scrollBarSize;
127+
if (hasHozScroll) {
128+
style.paddingBottom = 0;
129+
} else {
130+
style.paddingBottom = scrollBarSize;
131+
style[marginName] = 0;
132+
}
133+
}
134+
135+
dom.setStyle(this.headerNode, style);
106136
}
107137
}
108138

@@ -113,6 +143,7 @@ export default function fixed(BaseComponent) {
113143
className,
114144
prefix,
115145
fixedHeader,
146+
lockType,
116147
maxBodyHeight,
117148
...others
118149
} = this.props;
@@ -132,9 +163,17 @@ export default function fixed(BaseComponent) {
132163
[className]: className,
133164
});
134165
}
166+
const event = lockType
167+
? {}
168+
: {
169+
onScroll: this.onScroll,
170+
};
171+
135172
return (
136173
<BaseComponent
137174
{...others}
175+
{...event}
176+
lockType={lockType}
138177
components={components}
139178
className={className}
140179
prefix={prefix}

src/table/lock.jsx

+38-8
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ export default function lock(BaseComponent) {
288288

289289
const x = this.bodyNode.scrollLeft,
290290
y = this.bodyNode.scrollTop;
291-
292291
if (lockLeftBody) {
293292
lockLeftBody.scrollTop = y;
294293
}
@@ -409,31 +408,57 @@ export default function lock(BaseComponent) {
409408
}
410409

411410
adjustBodySize() {
411+
const { rtl } = this.props;
412+
const header = this.headerNode;
413+
const paddingName = rtl ? 'paddingLeft' : 'paddingRight';
414+
const marginName = rtl ? 'marginLeft' : 'marginRight';
415+
const scrollBarSize = dom.scrollbar().width;
416+
const style = {
417+
[paddingName]: scrollBarSize,
418+
[marginName]: scrollBarSize,
419+
};
420+
412421
if (this.isLock()) {
413-
const { rtl } = this.props;
414422
const body = this.bodyNode,
415423
lockLeftBody = this.bodyLeftNode,
416424
lockRightBody = this.bodyRightNode,
417425
lockRightBodyWrapper = this.getWrapperNode('right'),
418426
scrollbar = dom.scrollbar(),
419427
bodyHeight = body.offsetHeight,
420-
hasHozScroll = body.scrollWidth > body.clientWidth,
421428
hasVerScroll = body.scrollHeight > body.clientHeight,
422-
width = hasVerScroll ? scrollbar.width : 0,
423-
lockBodyHeight =
424-
bodyHeight - (hasHozScroll ? scrollbar.height : 0);
429+
width = hasVerScroll ? scrollBarSize : 0,
430+
lockBodyHeight = bodyHeight - scrollbar.height;
431+
432+
if (!hasVerScroll || !+scrollBarSize) {
433+
style[paddingName] = 0;
434+
style[marginName] = 0;
435+
}
425436

437+
if (+scrollBarSize) {
438+
style.marginBottom = -scrollBarSize;
439+
style.paddingBottom = 0;
440+
} else {
441+
style.marginBottom = -20;
442+
style.paddingBottom = 20;
443+
}
444+
445+
header && dom.setStyle(header, style);
426446
lockLeftBody &&
427447
dom.setStyle(lockLeftBody, 'max-height', lockBodyHeight);
428448
lockRightBody &&
429449
dom.setStyle(lockRightBody, 'max-height', lockBodyHeight);
430-
431450
lockRightBodyWrapper &&
451+
+scrollBarSize &&
432452
dom.setStyle(
433453
lockRightBodyWrapper,
434454
rtl ? 'left' : 'right',
435455
`${width}px`
436456
);
457+
} else {
458+
style.marginBottom = -scrollBarSize;
459+
style.paddingBottom = scrollBarSize;
460+
style[marginName] = 0;
461+
header && dom.setStyle(header, style);
437462
}
438463
}
439464

@@ -506,7 +531,7 @@ export default function lock(BaseComponent) {
506531
this.tableInc.props.dataSource.forEach((item, index) => {
507532
// record may be a string
508533
const rowIndex =
509-
typeof record === 'object' && '__rowIndex' in item
534+
typeof item === 'object' && '__rowIndex' in item
510535
? item.__rowIndex
511536
: index;
512537

@@ -614,6 +639,7 @@ export default function lock(BaseComponent) {
614639
prefix,
615640
components,
616641
className,
642+
dataSource,
617643
...others
618644
} = this.props;
619645
let {
@@ -638,11 +664,13 @@ export default function lock(BaseComponent) {
638664
components.Row = components.Row || LockRow;
639665
className = classnames({
640666
[`${prefix}table-lock`]: true,
667+
[`${prefix}table-wrap-empty`]: !dataSource.length,
641668
[className]: className,
642669
});
643670
const content = [
644671
<BaseComponent
645672
{...others}
673+
dataSource={dataSource}
646674
key="lock-left"
647675
columns={lockLeftChildren}
648676
className={`${prefix}table-lock-left`}
@@ -655,6 +683,7 @@ export default function lock(BaseComponent) {
655683
/>,
656684
<BaseComponent
657685
{...others}
686+
dataSource={dataSource}
658687
key="lock-right"
659688
columns={lockRightChildren}
660689
className={`${prefix}table-lock-right`}
@@ -669,6 +698,7 @@ export default function lock(BaseComponent) {
669698
return (
670699
<BaseComponent
671700
{...others}
701+
dataSource={dataSource}
672702
columns={normalizedChildren}
673703
prefix={prefix}
674704
wrapperContent={content}

src/table/main.scss

+29-3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
}
5656
&-affix {
5757
z-index: 1;
58+
overflow: hidden;
5859
}
5960
&-header-resizable {
6061
position: relative;
@@ -212,8 +213,14 @@
212213
font-size: $table-th-font-size;
213214
}
214215

216+
#{$table-prefix}-header {
217+
margin-bottom: -20px;
218+
padding-bottom: 20px;
219+
}
220+
215221
#{$table-prefix}-body {
216222
font-size: $table-body-font-size;
223+
position: relative;
217224
}
218225

219226
#{$table-prefix}-fixed {
@@ -223,6 +230,8 @@
223230
}
224231
#{$table-prefix}-header {
225232
background: $table-th-bg;
233+
padding-bottom: 20px;
234+
margin-bottom: -20px;
226235
}
227236
@include table-border(0);
228237
&#{$table-prefix}-group {
@@ -274,8 +283,19 @@
274283
}
275284
}
276285

277-
#{$table-prefix}-header-inner {
278-
overflow: hidden;
286+
#{$table-prefix}-wrap-empty {
287+
#{$table-prefix}-lock-left,
288+
#{$table-prefix}-lock-right {
289+
td {
290+
border: none;
291+
}
292+
#{$table-prefix}-empty {
293+
display: none;
294+
}
295+
}
296+
> #{$table-prefix}-inner > #{$table-prefix}-body > table {
297+
table-layout: auto;
298+
}
279299
}
280300

281301
#{$table-prefix}-lock-left,
@@ -285,17 +305,23 @@
285305
top: 0;
286306
z-index: 1;
287307
border: 0;
308+
transition: box-shadow .3s ease;
309+
overflow: hidden;
288310
table {
289311
width: auto;
290312
}
291313
#{$table-prefix}-body {
292-
overflow: hidden;
314+
overflow-y: scroll;
315+
overflow-x: hidden;
316+
margin-right: -20px;
317+
padding-right: 0;
293318
}
294319
}
295320

296321
#{$table-prefix}-lock-right {
297322
right: 0;
298323
left: auto;
324+
299325
&.shadow {
300326
box-shadow: -2px 0 3px rgba(0, 0, 0, .12);
301327
}

src/table/virtual.jsx

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default function virtual(BaseComponent) {
2828
* 在内容区域滚动的时候触发的函数
2929
*/
3030
onBodyScroll: PropTypes.func,
31+
onScroll: PropTypes.func,
3132
...BaseComponent.propTypes,
3233
};
3334

@@ -39,6 +40,7 @@ export default function virtual(BaseComponent) {
3940
components: {},
4041
prefix: 'next-',
4142
onBodyScroll: noop,
43+
onScroll: noop,
4244
};
4345

4446
static childContextTypes = {
@@ -151,6 +153,7 @@ export default function virtual(BaseComponent) {
151153
if (typeof rowHeight === 'function') {
152154
return 0;
153155
}
156+
154157
return this.start * rowHeight;
155158
}
156159

0 commit comments

Comments
 (0)