Commit a00e989ba3f0e850862f759a335e812d5e369900

Authored by Aresn
Committed by GitHub
2 parents 4ad72493 c1115edd

Merge pull request #3178 from huanghong1125/2.0

fixed table scrollbar bug
examples/routers/table.vue
1 1 <template>
2 2 <div>
3   - <Table border ref="selection" :columns="columns4" :data="data1"></Table>
  3 + <Table border ref="selection" :columns="columns4" :data="data1" :height='258'></Table>
4 4 <Button @click="handleSetData">Set Data</Button>
5 5 <Button @click="handleClearData">Clear Data</Button>
6 6 <Button @click="handleSelectAll(true)">Set all selected</Button>
7 7 <Button @click="handleSelectAll(false)">Cancel all selected</Button>
8   - <div style="margin:20px 0px;">
9   - <Table :data="tableData1" :columns="tableColumns1" style="width: 100%;" stripe></Table>
  8 + <div style='margin:20px 0px'>
  9 + <Table border :columns="columns2" :data="data3"></Table>
  10 + </div>
  11 + <div style='margin:20px 0px'>
  12 + <Table :height='200' border :columns="columns2" :data="data3"></Table>
  13 + </div>
  14 + <div style='margin:20px 0px'>
  15 + <Table :width='600' border :columns="columns2" :data="data3"></Table>
  16 + </div>
  17 + <div style='margin:20px 0px'>
  18 + <Table :width='600' :height='200' border :columns="columns2" :data="data3"></Table>
  19 + </div>
  20 + <div style='margin:20px 0px;'>
  21 + Table scrolling <i-switch v-model="fixedHeader" style="margin-right: 5px"></i-switch>
  22 + <Table :data="tableData1" :columns="tableColumns1" :height="fixedHeader ? 250 : ''" stripe size='small'></Table>
10 23 <div style="margin: 10px;overflow: hidden">
11 24 <div style="float: right;">
12 25 <Page :total="100" show-sizer :current="1" @on-change="changePage"></Page>
13 26 </div>
14 27 </div>
15 28 </div>
  29 +
16 30 </div>
17 31 </template>
18 32 <script>
... ... @@ -27,7 +41,8 @@
27 41 },
28 42 {
29 43 title: 'Name',
30   - key: 'name'
  44 + key: 'name',
  45 + width: 260
31 46 },
32 47 {
33 48 title: 'Age',
... ... @@ -35,13 +50,110 @@
35 50 },
36 51 {
37 52 title: 'Address',
38   - key: 'address'
  53 + key: 'address',
  54 + width: 260
  55 + },
  56 + {
  57 + title: 'Address',
  58 + key: 'address',
  59 + width: 260
39 60 }
40 61 ],
41 62 data1: [
42 63  
43 64 ],
44   -
  65 + columns2: [
  66 + {
  67 + title: 'Name',
  68 + key: 'name',
  69 + width: 100,
  70 + fixed: 'left'
  71 + },
  72 + {
  73 + title: 'Age',
  74 + key: 'age',
  75 + width: 100
  76 + },
  77 + {
  78 + title: 'Province',
  79 + key: 'province',
  80 + width: 100
  81 + },
  82 + {
  83 + title: 'City',
  84 + key: 'city',
  85 + width: 100
  86 + },
  87 + {
  88 + title: 'Address',
  89 + key: 'address',
  90 + width: 200
  91 + },
  92 + {
  93 + title: 'Postcode',
  94 + key: 'zip',
  95 + width: 100,
  96 + fixed: 'right',
  97 + },
  98 + {
  99 + title: 'Action',
  100 + key: 'action',
  101 + fixed: 'right',
  102 + width: 120,
  103 + render: (h, params) => {
  104 + return h('div', [
  105 + h('Button', {
  106 + props: {
  107 + type: 'text',
  108 + size: 'small'
  109 + }
  110 + }, 'View'),
  111 + h('Button', {
  112 + props: {
  113 + type: 'text',
  114 + size: 'small'
  115 + }
  116 + }, 'Edit')
  117 + ]);
  118 + }
  119 + }
  120 + ],
  121 + data3: [
  122 + {
  123 + name: 'John Brown',
  124 + age: 18,
  125 + address: 'New York No. 1 Lake Park',
  126 + province: 'America',
  127 + city: 'New York',
  128 + zip: 100000
  129 + },
  130 + {
  131 + name: 'Jim Green',
  132 + age: 24,
  133 + address: 'Washington, D.C. No. 1 Lake Park',
  134 + province: 'America',
  135 + city: 'Washington, D.C.',
  136 + zip: 100000
  137 + },
  138 + {
  139 + name: 'Joe Black',
  140 + age: 30,
  141 + address: 'Sydney No. 1 Lake Park',
  142 + province: 'Australian',
  143 + city: 'Sydney',
  144 + zip: 100000
  145 + },
  146 + {
  147 + name: 'Jon Snow',
  148 + age: 26,
  149 + address: 'Ottawa No. 2 Lake Park',
  150 + province: 'Canada',
  151 + city: 'Ottawa',
  152 + zip: 100000
  153 + }
  154 + ],
  155 +
  156 + fixedHeader: false,
45 157 tableData1: [],
46 158 tableColumns1: [
47 159 {
... ... @@ -65,7 +177,7 @@
65 177 key: 'data5'
66 178 },
67 179 {
68   - title: 'Data6',
  180 + title: 'Data6Data6Data6Data6Data6Data6Data6Data6Data6Data6Data6',
69 181 key: 'data6'
70 182 },
71 183 ]
... ... @@ -118,7 +230,7 @@
118 230 data3: Math.floor(Math.random () * 100000000),
119 231 data4: Math.floor(Math.random () * Math.random () * 10000),
120 232 data5: Math.floor(Math.random () * Math.random () * 1000000),
121   - data6: Math.floor(Math.random () * Math.random () * 100000000),
  233 + data6: ''+Math.floor(Math.random () * Math.random () * 100000000)+Math.floor(Math.random () * 100000000)+Math.floor(Math.random () * 100000000),
122 234 });
123 235 }
124 236 this.tableData1 = data;
... ...
src/components/table/mixin.js
... ... @@ -25,13 +25,19 @@ export default {
25 25 width = this.columnsWidth[column._index].width;
26 26 }
27 27 // when browser has scrollBar,set a width to resolve scroll position bug
28   - if (width && this.columns.length === index + 1 && top && this.$parent.bodyHeight !== 0) {
29   - width += this.$parent.scrollBarWidth;
  28 + if (width && this.columns.length === index + 1 && top && this.$parent.bodyHeight !== 0 && column.fixed!=='left' && !this.fixed) {
  29 + let scrollBarWidth = this.$parent.scrollBarWidth;
  30 + if (!this.$parent.showVerticalScrollBar) scrollBarWidth = 0;
  31 + width += scrollBarWidth;
30 32 }
31 33 // when fixed type,reset first right fixed column's width
32   - if (this.fixed === 'right') {
33   - const firstFixedIndex = this.columns.findIndex((col) => col.fixed === 'right');
34   - if (firstFixedIndex === index) width += this.$parent.scrollBarWidth;
  34 + if (this.fixed === 'right' && top ) {
  35 + //const firstFixedIndex = this.columns.findIndex((col) => col.fixed === 'right');
  36 + if (this.columns.length === index + 1) {
  37 + let scrollBarWidth = this.$parent.scrollBarWidth;
  38 + if (!this.$parent.showVerticalScrollBar) scrollBarWidth = 0;
  39 + width += scrollBarWidth;
  40 + }
35 41 }
36 42 if (width === '0') width = '';
37 43 return width;
... ...
src/components/table/table-head.vue
... ... @@ -87,7 +87,12 @@
87 87 computed: {
88 88 styles () {
89 89 const style = Object.assign({}, this.styleObject);
90   - const width = this.$parent.bodyHeight === 0 ? parseInt(this.styleObject.width) : parseInt(this.styleObject.width) + this.$parent.scrollBarWidth;
  90 + let scrollBarWidth = this.$parent.scrollBarWidth;
  91 + if(!this.$parent.showVerticalScrollBar) scrollBarWidth = 0;
  92 +
  93 + let isLeftFixed = this.$el && this.$el.parentElement.className.indexOf('fixed-header')>0;
  94 + if(isLeftFixed) scrollBarWidth = 0;
  95 + const width = this.$parent.bodyHeight === 0 ? parseInt(this.styleObject.width) : parseInt(this.styleObject.width) + scrollBarWidth;
91 96 style.width = `${width}px`;
92 97 return style;
93 98 },
... ...
src/components/table/table.vue
... ... @@ -23,12 +23,12 @@
23 23 :obj-data="objData"></table-body>
24 24 </div>
25 25 <div
26   - :class="[prefixCls + '-tip']"
  26 + :class="[prefixCls + '-tip']" :style="bodyStyle" @scroll="handleBodyScroll"
27 27 v-show="((!!localeNoDataText && (!data || data.length === 0)) || (!!localeNoFilteredDataText && (!rebuildData || rebuildData.length === 0)))">
28 28 <table cellspacing="0" cellpadding="0" border="0">
29 29 <tbody>
30 30 <tr>
31   - <td :style="{ 'height': bodyStyle.height }">
  31 + <td :style="{'height':bodyStyle.height,'width':`${this.headerWidth}px`}">
32 32 <span v-html="localeNoDataText" v-if="!data || data.length === 0"></span>
33 33 <span v-html="localeNoFilteredDataText" v-else></span>
34 34 </td>
... ... @@ -186,7 +186,10 @@
186 186 bodyRealHeight: 0,
187 187 scrollBarWidth: getScrollBarSize(),
188 188 currentContext: this.context,
189   - cloneData: deepCopy(this.data) // when Cell has a button to delete row data, clickCurrentRow will throw an error, so clone a data
  189 + cloneData: deepCopy(this.data), // when Cell has a button to delete row data, clickCurrentRow will throw an error, so clone a data
  190 + showVerticalScrollBar:false,
  191 + showHorizontalScrollBar:false,
  192 + headerWidth:0
190 193 };
191 194 },
192 195 computed: {
... ... @@ -252,7 +255,7 @@
252 255 if (this.bodyHeight > this.bodyRealHeight) {
253 256 width = this.tableWidth;
254 257 } else {
255   - width = this.tableWidth - this.scrollBarWidth;
  258 + width = this.tableWidth - (this.showVerticalScrollBar?this.scrollBarWidth:0);
256 259 }
257 260 }
258 261 // const width = this.bodyHeight === 0 ? this.tableWidth : this.tableWidth - this.scrollBarWidth;
... ... @@ -275,8 +278,9 @@
275 278 this.rightFixedColumns.forEach((col) => {
276 279 if (col.fixed && col.fixed === 'right') width += col._width;
277 280 });
278   - width += this.scrollBarWidth;
  281 + //width += this.scrollBarWidth;
279 282 style.width = `${width}px`;
  283 + style.right = `${this.showVerticalScrollBar?this.scrollBarWidth:0}px`;
280 284 return style;
281 285 },
282 286 bodyStyle () {
... ... @@ -291,11 +295,11 @@
291 295 fixedBodyStyle () {
292 296 let style = {};
293 297 if (this.bodyHeight !== 0) {
294   - let height = this.bodyHeight + this.scrollBarWidth - 1;
  298 + let height = this.bodyHeight + (!this.showHorizontalScrollBar?this.scrollBarWidth:0) - 1;
295 299  
296 300 // #2102 ้‡Œ๏ผŒๅฆ‚ๆžœ Table ๆฒกๆœ‰่ฎพ็ฝฎ width๏ผŒ่€Œๆ˜ฏ้›†ๆˆ็ˆถ็บง็š„ width๏ผŒๅ›บๅฎšๅˆ—ไนŸๅบ”่ฏฅไธๅŒ…ๅซๆปšๅŠจๆก้ซ˜ๅบฆ๏ผŒๆ‰€ไปฅ่ฟ™้‡Œ็›ดๆŽฅ่ฎก็ฎ—่กจๆ ผๅฎฝๅบฆ
297 301 const tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
298   - if ((this.width && this.width < this.tableWidth) || tableWidth < this.tableWidth){
  302 + if ((this.width && this.width < this.tableWidth) || tableWidth < this.tableWidth+(this.showVerticalScrollBar?this.scrollBarWidth:0)){
299 303 height = this.bodyHeight;
300 304 }
301 305 // style.height = this.scrollBarWidth > 0 ? `${this.bodyHeight}px` : `${this.bodyHeight - 1}px`;
... ... @@ -310,7 +314,7 @@
310 314 if (col.fixed && col.fixed === 'left') {
311 315 left.push(col);
312 316 } else {
313   - other.push(col);
  317 + //other.push(col);
314 318 }
315 319 });
316 320 return left.concat(other);
... ... @@ -322,7 +326,7 @@
322 326 if (col.fixed && col.fixed === 'right') {
323 327 right.push(col);
324 328 } else {
325   - other.push(col);
  329 + //other.push(col);
326 330 }
327 331 });
328 332 return right.concat(other);
... ... @@ -347,7 +351,13 @@
347 351 this.tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
348 352 }
349 353 this.columnsWidth = {};
350   - if (!this.$refs.tbody) return;
  354 + this.$nextTick(()=>{
  355 + this.headerWidth = this.$refs.header.childNodes[0].offsetWidth;
  356 + if (!this.$refs.tbody) {
  357 + this.showVerticalScrollBar = false;
  358 + return;
  359 + }
  360 + });
351 361 this.$nextTick(() => {
352 362 let columnsWidth = {};
353 363 let autoWidthIndex = -1;
... ... @@ -357,7 +367,6 @@
357 367 const $tr = this.$refs.tbody.$el.querySelectorAll('tbody tr');
358 368 if ($tr.length === 0) return;
359 369 const $td = $tr[0].children;
360   -
361 370 for (let i = 0; i < $td.length; i++) { // can not use forEach in Firefox
362 371 const column = this.cloneColumns[i];
363 372  
... ... @@ -374,6 +383,36 @@
374 383 };
375 384 }
376 385 this.columnsWidth = columnsWidth;
  386 + this.$nextTick(()=>{
  387 + this.fixedHeader();
  388 + if (this.$refs.tbody) {
  389 + let bodyContentEl = this.$refs.tbody.$el;
  390 + let bodyEl = bodyContentEl.parentElement;
  391 + let bodyContentHeight = bodyContentEl.offsetHeight;
  392 + let bodyContentWidth = bodyContentEl.offsetWidth;
  393 + let bodyWidth = bodyEl.offsetWidth;
  394 + let bodyHeight = bodyEl.offsetHeight;
  395 + let scrollBarWidth = 0;
  396 + if (bodyWidth < bodyContentWidth + (bodyHeight<bodyContentHeight?this.scrollBarWidth : 0)) {
  397 + scrollBarWidth = this.scrollBarWidth;
  398 + }
  399 +
  400 + this.showVerticalScrollBar = this.bodyHeight? bodyHeight - scrollBarWidth < bodyContentHeight : false;
  401 + this.showHorizontalScrollBar = bodyWidth < bodyContentWidth + (this.showVerticalScrollBar?this.scrollBarWidth:0);
  402 +
  403 + if(this.showVerticalScrollBar){
  404 + bodyEl.classList.add(this.prefixCls +'-overflowY');
  405 + }else{
  406 + bodyEl.classList.remove(this.prefixCls +'-overflowY');
  407 + }
  408 + if(this.showHorizontalScrollBar){
  409 + bodyEl.classList.add(this.prefixCls +'-overflowX');
  410 + }else{
  411 + bodyEl.classList.remove(this.prefixCls +'-overflowX');
  412 + }
  413 +
  414 + }
  415 + });
377 416 }
378 417 });
379 418 // get table real height,for fixed when set height prop,but height < table's height,show scrollBarWidth
... ... @@ -478,6 +517,7 @@
478 517 }
479 518 this.$emit('on-selection-change', selection);
480 519 },
  520 +
481 521 fixedHeader () {
482 522 if (this.height) {
483 523 this.$nextTick(() => {
... ... @@ -795,6 +835,7 @@
795 835 deep: true
796 836 },
797 837 height () {
  838 + this.handleResize();
798 839 this.fixedHeader();
799 840 }
800 841 }
... ...
src/styles/components/table.less
... ... @@ -71,7 +71,19 @@
71 71 overflow: hidden;
72 72 }
73 73 &-body{
74   - overflow: auto;
  74 + //overflow: auto;
  75 + //position: relative;
  76 +
  77 + }
  78 + &-overflowX{
  79 + overflow-x: scroll;
  80 + }
  81 + &-overflowY{
  82 + overflow-y: scroll;
  83 + }
  84 + &-tip{
  85 + overflow-x: auto;
  86 + overflow-y: hidden;
75 87 //position: relative;
76 88 }
77 89  
... ... @@ -273,7 +285,7 @@
273 285 box-shadow: -2px 0 6px -2px rgba(0, 0, 0, 0.2);
274 286 }
275 287 &-fixed-header{
276   - overflow: hidden;
  288 + overflow: visible;
277 289 &-with-empty{
278 290 .@{table-prefix-cls}-hidden{
279 291 .@{table-prefix-cls}-sort{
... ...