Commit a3547c1b41b9f411fdc00d327ee093a0cd260dfe

Authored by 梁灏
1 parent abdec99d

update Table

update Table
src/components/table/cell.vue 0 → 100644
  1 +<template>
  2 + <div :class="[prefixCls + '-cell']">
  3 + <template v-if="renderType === 'index'">{{index + 1}}</template>
  4 + <template v-if="renderType === 'normal'">{{{ row[column.key] }}}</template>
  5 + </div>
  6 +</template>
  7 +<script>
  8 + export default {
  9 + props: {
  10 + prefixCls: String,
  11 + row: Object,
  12 + column: Object,
  13 + index: Number
  14 + },
  15 + data () {
  16 + return {
  17 + renderType: '',
  18 + uid: -1
  19 + }
  20 + },
  21 + methods: {
  22 + compile () {
  23 + if (this.column.render) {
  24 + const template = this.column.render(this.row, this.column, this.index);
  25 + const cell = document.createElement('div');
  26 + cell.innerHTML = template;
  27 + const _oldParentChildLen = this.$parent.$parent.$children.length;
  28 + this.$parent.$parent.$compile(cell);
  29 + const _newParentChildLen = this.$parent.$parent.$children.length;
  30 +
  31 + if (_oldParentChildLen !== _newParentChildLen) { // if render normal html node, do not tag
  32 + this.uid = this.$parent.$parent.$children[this.$parent.$parent.$children.length - 1]._uid; // tag it, and delete when data or columns update
  33 + }
  34 + this.$el.innerHTML = '';
  35 + this.$el.appendChild(cell);
  36 + }
  37 + },
  38 + destroy () {
  39 + for (let i = 0; i < this.$parent.$parent.$children.length; i++) {
  40 + if (this.$parent.$parent.$children[i]._uid === this.uid) {
  41 + this.$parent.$parent.$children[i].$destroy();
  42 + }
  43 + }
  44 + }
  45 + },
  46 + compiled () {
  47 + if (this.column.type === 'index') {
  48 + this.renderType = 'index';
  49 + } else if (this.column.render) {
  50 + this.renderType = 'render';
  51 + } else {
  52 + this.renderType = 'normal';
  53 + }
  54 + },
  55 + ready () {
  56 + this.compile();
  57 + },
  58 + beforeDestroy () {
  59 + this.destroy();
  60 + },
  61 + watch: {
  62 + index () {
  63 + this.destroy();
  64 + this.compile();
  65 + }
  66 + }
  67 + }
  68 +</script>
0 \ No newline at end of file 69 \ No newline at end of file
src/components/table/table.vue
@@ -26,12 +26,19 @@ @@ -26,12 +26,19 @@
26 @mouseleave.stop="handleMouseOut(index)" 26 @mouseleave.stop="handleMouseOut(index)"
27 @click.stop="highlightCurrentRow(index)"> 27 @click.stop="highlightCurrentRow(index)">
28 <td v-for="column in cloneColumns" :class="alignCls(column)"> 28 <td v-for="column in cloneColumns" :class="alignCls(column)">
29 - <div :class="[prefixCls + '-cell']">  
30 - <template v-if="column.type === 'selection'">  
31 - <Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox>  
32 - </template>  
33 - <template v-else>{{{ renderRow(row, column, index) }}}</template> 29 + <div :class="[prefixCls + '-cell']" v-if="column.type === 'selection'">
  30 + <Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox>
34 </div> 31 </div>
  32 + <Cell v-else :prefix-cls="prefixCls" :row="row" :column="column" :index="index"></Cell>
  33 + <!--<div :class="[prefixCls + '-cell']" v-else>-->
  34 + <!--{{{ renderRow(row, column, index) }}}-->
  35 + <!--</div>-->
  36 + <!--<div :class="[prefixCls + '-cell']">-->
  37 + <!--<template v-if="column.type === 'selection'">-->
  38 + <!--<Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox>-->
  39 + <!--</template>-->
  40 + <!--<template v-else>{{{ renderRow(row, column, index) }}}</template>-->
  41 + <!--</div>-->
35 </td> 42 </td>
36 </tr> 43 </tr>
37 </tbody> 44 </tbody>
@@ -49,13 +56,14 @@ @@ -49,13 +56,14 @@
49 <script> 56 <script>
50 import TableHead from './table-head.vue'; 57 import TableHead from './table-head.vue';
51 import Checkbox from '../checkbox/checkbox.vue'; 58 import Checkbox from '../checkbox/checkbox.vue';
  59 + import Cell from './cell.vue';
52 import Mixin from './mixin'; 60 import Mixin from './mixin';
53 import { oneOf, getStyle, deepCopy } from '../../utils/assist'; 61 import { oneOf, getStyle, deepCopy } from '../../utils/assist';
54 const prefixCls = 'ivu-table'; 62 const prefixCls = 'ivu-table';
55 63
56 export default { 64 export default {
57 mixins: [ Mixin ], 65 mixins: [ Mixin ],
58 - components: { TableHead, Checkbox }, 66 + components: { TableHead, Checkbox, Cell },
59 props: { 67 props: {
60 data: { 68 data: {
61 type: Array, 69 type: Array,
@@ -108,6 +116,9 @@ @@ -108,6 +116,9 @@
108 compiledUids: [], 116 compiledUids: [],
109 cloneData: deepCopy(this.data), 117 cloneData: deepCopy(this.data),
110 cloneColumns: deepCopy(this.columns), 118 cloneColumns: deepCopy(this.columns),
  119 + leftFixedColumns: [],
  120 + rightFixedColumns: [],
  121 + centerColumns: [],
111 showSlotHeader: true, 122 showSlotHeader: true,
112 showSlotFooter: true, 123 showSlotFooter: true,
113 bodyHeight: 0 124 bodyHeight: 0
@@ -147,53 +158,25 @@ @@ -147,53 +158,25 @@
147 rowClsName (index) { 158 rowClsName (index) {
148 return this.rowClassName(this.data[index], index); 159 return this.rowClassName(this.data[index], index);
149 }, 160 },
150 - renderRow (row, column, index) {  
151 - return column.type === 'index' ? index + 1 : column.render ? '' : row[column.key];  
152 - },  
153 - compileRender (update = false) { 161 + handleResize () {
154 this.$nextTick(() => { 162 this.$nextTick(() => {
155 - if (update) {  
156 - for (let i = 0; i < this.$parent.$children.length; i++) {  
157 - const index = this.compiledUids.indexOf(this.$parent.$children[i]._uid);  
158 - if (index > -1) {  
159 - this.$parent.$children[i].$destroy();  
160 - this.compiledUids.splice(index, 1);  
161 - i--;  
162 - }  
163 - } 163 + const allWidth = !this.columns.some(cell => !cell.width);
  164 + if (allWidth) {
  165 + this.tableWidth = this.columns.map(cell => cell.width).reduce((a, b) => a + b);
  166 + } else {
  167 + this.tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
164 } 168 }
165 -  
166 - const $el = this.$els.render;  
167 - for (let i = 0; i < this.cloneColumns.length; i++) {  
168 - const column = this.cloneColumns[i];  
169 - if (column.render) {  
170 - for (let j = 0; j < this.data.length; j++) {  
171 - // todo 做一个缓存,只在需要改render时再重新编译,data改变时不用再编译  
172 - const row = this.data[j];  
173 - const template = column.render(row, column, j);  
174 - const cell = document.createElement('div');  
175 - cell.innerHTML = template;  
176 - const _oldParentChildLen = this.$parent.$children.length;  
177 - this.$parent.$compile(cell);  
178 - const _newParentChildLen = this.$parent.$children.length;  
179 -  
180 - if (_oldParentChildLen !== _newParentChildLen) { // if render normal html node, do not tag  
181 - this.compiledUids.push(this.$parent.$children[this.$parent.$children.length - 1]._uid); // tag it, and delete when data or columns update  
182 - }  
183 - $el.children[j].children[i].children[0].innerHTML = '';  
184 - $el.children[j].children[i].children[0].appendChild(cell); 169 + this.$nextTick(() => {
  170 + this.columnsWidth = [];
  171 + let autoWidthIndex = -1
  172 + if (allWidth) autoWidthIndex = this.cloneColumns.findIndex(cell => !cell.width);
  173 + this.$els.tbody.querySelectorAll('tbody tr')[0].querySelectorAll('td').forEach((cell, index) => {
  174 + if (index === autoWidthIndex) {
  175 + this.columnsWidth.push(parseInt(getStyle(cell, 'width')) - 1);
  176 + } else {
  177 + this.columnsWidth.push(parseInt(getStyle(cell, 'width')));
185 } 178 }
186 - }  
187 - }  
188 - this.handleResize();  
189 - });  
190 - },  
191 - handleResize () {  
192 - this.tableWidth = parseInt(getStyle(this.$el, 'width'));  
193 - this.$nextTick(() => {  
194 - this.columnsWidth = [];  
195 - this.$els.tbody.querySelectorAll('tbody tr')[0].querySelectorAll('td').forEach((cell) => {  
196 - this.columnsWidth.push(parseInt(getStyle(cell, 'width'))); 179 + });
197 }); 180 });
198 }); 181 });
199 }, 182 },
@@ -282,6 +265,9 @@ @@ -282,6 +265,9 @@
282 center.push(col); 265 center.push(col);
283 } 266 }
284 }); 267 });
  268 + this.leftFixedColumns = left;
  269 + this.rightFixedColumns = right;
  270 + this.centerColumns = center;
285 this.cloneColumns = left.concat(center).concat(right); 271 this.cloneColumns = left.concat(center).concat(right);
286 } 272 }
287 }, 273 },
@@ -291,7 +277,7 @@ @@ -291,7 +277,7 @@
291 this.showSlotFooter = this.$els.footer.innerHTML.replace(/\n/g, '').replace(/<!--[\w\W\r\n]*?-->/gmi, '') !== ''; 277 this.showSlotFooter = this.$els.footer.innerHTML.replace(/\n/g, '').replace(/<!--[\w\W\r\n]*?-->/gmi, '') !== '';
292 }, 278 },
293 ready () { 279 ready () {
294 - this.compileRender(); 280 + this.handleResize();
295 this.fixedHeader(); 281 this.fixedHeader();
296 window.addEventListener('resize', this.handleResize, false); 282 window.addEventListener('resize', this.handleResize, false);
297 }, 283 },
@@ -302,14 +288,14 @@ @@ -302,14 +288,14 @@
302 data: { 288 data: {
303 handler () { 289 handler () {
304 this.cloneData = deepCopy(this.data); 290 this.cloneData = deepCopy(this.data);
305 - this.compileRender(true); 291 + this.handleResize();
306 }, 292 },
307 deep: true 293 deep: true
308 }, 294 },
309 columns: { 295 columns: {
310 handler () { 296 handler () {
311 this.parseColumns(); 297 this.parseColumns();
312 - this.compileRender(true); 298 + this.handleResize();
313 }, 299 },
314 deep: true 300 deep: true
315 }, 301 },
src/styles/components/table.less
@@ -9,10 +9,33 @@ @@ -9,10 +9,33 @@
9 background-color: #fff; 9 background-color: #fff;
10 border: 1px solid @border-color-base; 10 border: 1px solid @border-color-base;
11 border-bottom: 0; 11 border-bottom: 0;
  12 + border-right: 0;
12 border-collapse: collapse; 13 border-collapse: collapse;
13 box-sizing: border-box; 14 box-sizing: border-box;
14 position: relative; 15 position: relative;
15 16
  17 + &:before{
  18 + content: '';
  19 + width: 100%;
  20 + height: 1px;
  21 + position: absolute;
  22 + left: 0;
  23 + bottom: 0;
  24 + background-color: @border-color-base;
  25 + z-index: 1;
  26 + }
  27 +
  28 + &:after{
  29 + content: '';
  30 + width: 1px;
  31 + height: 100%;
  32 + position: absolute;
  33 + top: 0;
  34 + right: 0;
  35 + background-color: @border-color-base;
  36 + z-index: 1;
  37 + }
  38 +
16 &-with-header{ 39 &-with-header{
17 border-radius: @border-radius-base @border-radius-base 0 0; 40 border-radius: @border-radius-base @border-radius-base 0 0;
18 } 41 }
@@ -36,8 +59,9 @@ @@ -36,8 +59,9 @@
36 } 59 }
37 60
38 &-body{ 61 &-body{
39 - overflow-x: hidden;  
40 - overflow-y: auto; 62 + //overflow-x: hidden;
  63 + //overflow-y: auto;
  64 + overflow: auto;
41 position: relative; 65 position: relative;
42 } 66 }
43 67
@@ -91,7 +115,8 @@ @@ -91,7 +115,8 @@
91 } 115 }
92 116
93 & table{ 117 & table{
94 - width: 100%; 118 + //width: 100%;
  119 + table-layout: fixed;
95 } 120 }
96 &-border{ 121 &-border{
97 th,td{ 122 th,td{
test/routers/table.vue
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <!--<i-table size="large" border stripe :columns="columns" :data="data"></i-table>--> 8 <!--<i-table size="large" border stripe :columns="columns" :data="data"></i-table>-->
9 <br> 9 <br>
10 <i-table 10 <i-table
  11 + style="width:450px"
11 border 12 border
12 highlight-row 13 highlight-row
13 :columns="columns" 14 :columns="columns"
@@ -57,7 +58,7 @@ @@ -57,7 +58,7 @@
57 title: '地址', 58 title: '地址',
58 key: 'address', 59 key: 'address',
59 align: 'center', 60 align: 'center',
60 -// width: 100 61 + width: 100,
61 // render (row, column, index) { 62 // render (row, column, index) {
62 // if (row.edit) { 63 // if (row.edit) {
63 // return `<i-input :value.sync="data[${index}].name"></i-input>`; 64 // return `<i-input :value.sync="data[${index}].name"></i-input>`;
@@ -72,7 +73,8 @@ @@ -72,7 +73,8 @@
72 fixed: 'right', 73 fixed: 'right',
73 width: 200, 74 width: 200,
74 render (row, column, index) { 75 render (row, column, index) {
75 - return `<i-button @click="edit(${index})">编辑</i-button>` 76 + return `<i-button @click="edit(${index})">${row.name}</i-button>`
  77 +// return `<a>${row.name}</a>`
76 } 78 }
77 } 79 }
78 ], 80 ],
@@ -140,14 +142,16 @@ @@ -140,14 +142,16 @@
140 }, 142 },
141 ready () { 143 ready () {
142 setTimeout(() => { 144 setTimeout(() => {
  145 + return;
143 // this.height = 150; 146 // this.height = 150;
144 - return  
145 - this.data.push({  
146 - name: '刘天娇2',  
147 - age: 272,  
148 - address: '北京市东城区2',  
149 - edit: false  
150 - }); 147 +// return
  148 +// this.data.push({
  149 +// name: '刘天娇2',
  150 +// age: 272,
  151 +// address: '北京市东城区2',
  152 +// edit: false
  153 +// });
  154 + this.data.splice(1, 1)
151 }, 1000); 155 }, 1000);
152 } 156 }
153 } 157 }