Commit 6dee0a655c72682adc2b6464592cb95213c83642

Authored by jingsam
2 parents e2645048 3d9e4f20

Merge remote-tracking branch 'upstream/master' into clean-css

src/components/table/cell.vue
1 1 <template>
2   - <div :class="[prefixCls + '-cell']">
  2 + <div :class="classes">
3 3 <template v-if="renderType === 'index'">{{index + 1}}</template>
  4 + <template v-if="renderType === 'selection'">
  5 + <Checkbox :checked="checked" @on-change="toggleSelect(index)"></Checkbox>
  6 + </template>
4 7 <template v-if="renderType === 'normal'">{{{ row[column.key] }}}</template>
5 8 </div>
6 9 </template>
7 10 <script>
  11 + import Checkbox from '../checkbox/checkbox.vue';
  12 +
8 13 export default {
  14 + components: { Checkbox },
9 15 props: {
10 16 prefixCls: String,
11 17 row: Object,
12 18 column: Object,
13   - index: Number
  19 + index: Number,
  20 + checked: Boolean,
  21 + fixed: Boolean
14 22 },
15 23 data () {
16 24 return {
... ... @@ -18,34 +26,51 @@
18 26 uid: -1
19 27 }
20 28 },
  29 + computed: {
  30 + classes () {
  31 + return [
  32 + `${this.prefixCls}-cell`,
  33 + {
  34 + [`${this.prefixCls}-hidden`]: !this.fixed && this.column.fixed && (this.column.fixed === 'left' || this.column.fixed === 'right')
  35 + }
  36 + ]
  37 + }
  38 + },
21 39 methods: {
22 40 compile () {
23 41 if (this.column.render) {
  42 + const $parent = this.$parent.$parent.$parent;
24 43 const template = this.column.render(this.row, this.column, this.index);
25 44 const cell = document.createElement('div');
26 45 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;
  46 + const _oldParentChildLen = $parent.$children.length;
  47 + $parent.$compile(cell);
  48 + const _newParentChildLen = $parent.$children.length;
30 49  
31 50 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
  51 + this.uid = $parent.$children[$parent.$children.length - 1]._uid; // tag it, and delete when data or columns update
33 52 }
34 53 this.$el.innerHTML = '';
35 54 this.$el.appendChild(cell);
36 55 }
37 56 },
38 57 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();
  58 + const $parent = this.$parent.$parent.$parent;
  59 + for (let i = 0; i < $parent.$children.length; i++) {
  60 + if ($parent.$children[i]._uid === this.uid) {
  61 + $parent.$children[i].$destroy();
42 62 }
43 63 }
  64 + },
  65 + toggleSelect (index) {
  66 + this.$parent.$parent.toggleSelect(index);
44 67 }
45 68 },
46 69 compiled () {
47 70 if (this.column.type === 'index') {
48 71 this.renderType = 'index';
  72 + } else if (this.column.type === 'selection') {
  73 + this.renderType = 'selection';
49 74 } else if (this.column.render) {
50 75 this.renderType = 'render';
51 76 } else {
... ...
src/components/table/table-body.vue
1 1 <template>
2   -
  2 + <table cellspacing="0" cellpadding="0" border="0" :style="style">
  3 + <colgroup>
  4 + <col v-for="column in columns" :width="setCellWidth(column, $index)">
  5 + </colgroup>
  6 + <tbody :class="[prefixCls + '-tbody']">
  7 + <tr
  8 + v-for="(index, row) in data"
  9 + :class="[prefixCls + '-row', rowClsName(index), {[prefixCls + '-row-highlight']: cloneData[index] && cloneData[index]._isHighlight, [prefixCls + '-row-hover']: cloneData[index] && cloneData[index]._isHover}]"
  10 + @mouseenter.stop="handleMouseIn(index)"
  11 + @mouseleave.stop="handleMouseOut(index)"
  12 + @click.stop="highlightCurrentRow(index)">
  13 + <td v-for="column in columns" :class="alignCls(column)">
  14 + <Cell
  15 + :fixed="fixed"
  16 + :prefix-cls="prefixCls"
  17 + :row="row"
  18 + :column="column"
  19 + :index="index"
  20 + :checked="cloneData[index] && cloneData[index]._isChecked"></Cell>
  21 + </td>
  22 + </tr>
  23 + </tbody>
  24 + </table>
3 25 </template>
4 26 <script>
  27 + import Cell from './cell.vue';
  28 + import Mixin from './mixin';
  29 +
5 30 export default {
  31 + mixins: [ Mixin ],
  32 + components: { Cell },
6 33 props: {
7   -
8   - },
9   - data () {
10   - return {
11   -
12   - }
13   - },
14   - computed: {
15   -
  34 + prefixCls: String,
  35 + style: Object,
  36 + columns: Array,
  37 + data: Array,
  38 + cloneData: Array,
  39 + fixed: Boolean
16 40 },
17 41 methods: {
18   -
  42 + setCellWidth (column, index) {
  43 + return this.$parent.setCellWidth(column, index);
  44 + },
  45 + rowClsName (index) {
  46 + return this.$parent.rowClassName(this.data[index], index);
  47 + },
  48 + handleMouseIn (index) {
  49 + this.$parent.handleMouseIn(index);
  50 + },
  51 + handleMouseOut (index) {
  52 + this.$parent.handleMouseOut(index);
  53 + },
  54 + highlightCurrentRow (index) {
  55 + this.$parent.highlightCurrentRow(index);
  56 + }
19 57 }
20 58 }
21 59 </script>
22 60 \ No newline at end of file
... ...
src/components/table/table-column.vue deleted
1   -<template>
2   -
3   -</template>
4   -<script>
5   - export default {
6   - props: {
7   -
8   - },
9   - data () {
10   - return {
11   -
12   - }
13   - },
14   - computed: {
15   -
16   - },
17   - methods: {
18   -
19   - }
20   - }
21   -</script>
22 0 \ No newline at end of file
src/components/table/table-head.vue
1 1 <template>
2   - <thead>
3   - <tr>
4   - <th v-for="column in columns" :class="alignCls(column)">
5   - <div :class="[prefixCls + '-cell']">
6   - <template v-if="column.type === 'selection'"><Checkbox :checked="isSelectAll" @on-change="selectAll"></Checkbox></template>
7   - <template v-else>{{{ renderHeader(column, $index) }}}</template>
8   - </div>
9   - </th>
10   - </tr>
11   - </thead>
  2 + <table cellspacing="0" cellpadding="0" border="0" :style="style">
  3 + <colgroup>
  4 + <col v-for="column in columns" :width="setCellWidth(column, $index)">
  5 + </colgroup>
  6 + <thead>
  7 + <tr>
  8 + <th v-for="column in columns" :class="alignCls(column)">
  9 + <div :class="[prefixCls + '-cell', {[prefixCls + '-hidden']: !fixed && column.fixed && (column.fixed === 'left' || column.fixed === 'right')}]">
  10 + <template v-if="column.type === 'selection'"><Checkbox :checked="isSelectAll" @on-change="selectAll"></Checkbox></template>
  11 + <template v-else>{{{ renderHeader(column, $index) }}}</template>
  12 + </div>
  13 + </th>
  14 + </tr>
  15 + </thead>
  16 + </table>
12 17 </template>
13 18 <script>
14 19 import Checkbox from '../checkbox/checkbox.vue';
... ... @@ -20,13 +25,10 @@
20 25 components: { Checkbox },
21 26 props: {
22 27 prefixCls: String,
  28 + style: Object,
23 29 columns: Array,
24   - cloneData: Array
25   - },
26   - data () {
27   - return {
28   -
29   - }
  30 + cloneData: Array,
  31 + fixed: Boolean
30 32 },
31 33 computed: {
32 34 isSelectAll () {
... ... @@ -34,6 +36,9 @@
34 36 }
35 37 },
36 38 methods: {
  39 + setCellWidth (column, index) {
  40 + return this.$parent.setCellWidth(column, index);
  41 + },
37 42 renderHeader (column, $index) {
38 43 if ('renderHeader' in this.columns[$index]) {
39 44 return this.columns[$index].renderHeader(column, $index);
... ... @@ -43,16 +48,17 @@
43 48 },
44 49 selectAll () {
45 50 const status = !this.isSelectAll;
  51 + this.$parent.selectAll(status);
46 52  
47   - let tmpData = deepCopy(this.cloneData);
48   - tmpData.forEach((data) => {
49   - data._isChecked = status;
50   - });
51   - this.cloneData = tmpData;
52   -
53   - if (status) {
54   - this.$parent.selectAll();
55   - }
  53 +// let tmpData = deepCopy(this.cloneData);
  54 +// tmpData.forEach((data) => {
  55 +// data._isChecked = status;
  56 +// });
  57 +// this.cloneData = tmpData;
  58 +//
  59 +// if (status) {
  60 +// this.$parent.selectAll();
  61 +// }
56 62 }
57 63 }
58 64 }
... ...
src/components/table/table.vue
... ... @@ -2,68 +2,63 @@
2 2 <div :class="classes" :style="styles">
3 3 <div :class="[prefixCls + '-title']" v-if="showSlotHeader" v-el:title><slot name="header"></slot></div>
4 4 <div :class="[prefixCls + '-header']" v-if="showHeader" v-el:header @mousewheel="handleMouseWheel">
5   - <table cellspacing="0" cellpadding="0" border="0" :style="tableStyle">
6   - <colgroup>
7   - <col v-for="column in cloneColumns" :width="setCellWidth(column, $index)">
8   - </colgroup>
9   - <thead
10   - is="table-head"
11   - :prefix-cls="prefixCls"
12   - :clone-data.sync="cloneData"
13   - :columns="cloneColumns"></thead>
14   - </table>
  5 + <table-head
  6 + :prefix-cls="prefixCls"
  7 + :style="tableStyle"
  8 + :columns="cloneColumns"
  9 + :clone-data="cloneData"></table-head>
15 10 </div>
16   - <div :class="[prefixCls + '-body']" :style="bodyStyle" @scroll="handleBodyScroll">
17   - <table cellspacing="0" cellpadding="0" border="0" :style="tableStyle" v-el:tbody>
18   - <colgroup>
19   - <col v-for="column in cloneColumns" :width="setCellWidth(column, $index)">
20   - </colgroup>
21   - <tbody :class="[prefixCls + '-tbody']" v-el:render>
22   - <tr
23   - v-for="(index, row) in data"
24   - :class="[prefixCls + '-row', rowClsName(index), {[prefixCls + '-row-highlight']: cloneData[index] && cloneData[index]._isHighlight, [prefixCls + '-row-hover']: cloneData[index] && cloneData[index]._isHover}]"
25   - @mouseenter.stop="handleMouseIn(index)"
26   - @mouseleave.stop="handleMouseOut(index)"
27   - @click.stop="highlightCurrentRow(index)">
28   - <td v-for="column in cloneColumns" :class="alignCls(column)">
29   - <div :class="[prefixCls + '-cell']" v-if="column.type === 'selection'">
30   - <Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox>
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>-->
42   - </td>
43   - </tr>
44   - </tbody>
45   - </table>
  11 + <div :class="[prefixCls + '-body']" :style="bodyStyle" v-el:body @scroll="handleBodyScroll">
  12 + <table-body
  13 + v-ref:tbody
  14 + :prefix-cls="prefixCls"
  15 + :style="tableStyle"
  16 + :columns="cloneColumns"
  17 + :data="data"
  18 + :clone-data="cloneData"></table-body>
46 19 </div>
47 20 <div :class="[prefixCls + '-fixed']">
48   -
  21 + <!--todo 设置个div头部-->
  22 + <table-head
  23 + fixed
  24 + :prefix-cls="prefixCls"
  25 + :style="fixedTableStyle"
  26 + :columns="leftFixedColumns"
  27 + :clone-data="cloneData"></table-head>
  28 + <table-body
  29 + fixed
  30 + :prefix-cls="prefixCls"
  31 + :style="fixedTableStyle"
  32 + :columns="leftFixedColumns"
  33 + :data="data"
  34 + :clone-data="cloneData"></table-body>
49 35 </div>
50 36 <div :class="[prefixCls + '-fixed-right']">
51   -
  37 + <table-head
  38 + fixed
  39 + :prefix-cls="prefixCls"
  40 + :style="fixedRightTableStyle"
  41 + :columns="rightFixedColumns"
  42 + :clone-data="cloneData"></table-head>
  43 + <table-body
  44 + fixed
  45 + :prefix-cls="prefixCls"
  46 + :style="fixedRightTableStyle"
  47 + :columns="rightFixedColumns"
  48 + :data="data"
  49 + :clone-data="cloneData"></table-body>
52 50 </div>
53 51 <div :class="[prefixCls + '-footer']" v-if="showSlotFooter" v-el:footer><slot name="footer"></slot></div>
54 52 </div>
55 53 </template>
56 54 <script>
57   - import TableHead from './table-head.vue';
58   - import Checkbox from '../checkbox/checkbox.vue';
59   - import Cell from './cell.vue';
60   - import Mixin from './mixin';
  55 + import tableHead from './table-head.vue';
  56 + import tableBody from './table-body.vue';
61 57 import { oneOf, getStyle, deepCopy } from '../../utils/assist';
62 58 const prefixCls = 'ivu-table';
63 59  
64 60 export default {
65   - mixins: [ Mixin ],
66   - components: { TableHead, Checkbox, Cell },
  61 + components: { tableHead, tableBody },
67 62 props: {
68 63 data: {
69 64 type: Array,
... ... @@ -82,6 +77,9 @@
82 77 return oneOf(value, ['small', 'large']);
83 78 }
84 79 },
  80 + width: {
  81 + type: [Number, String]
  82 + },
85 83 height: {
86 84 type: [Number, String]
87 85 },
... ... @@ -141,6 +139,7 @@
141 139 styles () {
142 140 let style = {};
143 141 if (!!this.height) style.height = `${this.height}px`;
  142 + if (!!this.width) style.width = `${this.width}px`;
144 143 return style;
145 144 },
146 145 tableStyle () {
... ... @@ -148,6 +147,16 @@
148 147 if (this.tableWidth !== 0) style.width = `${this.tableWidth}px`;
149 148 return style;
150 149 },
  150 + fixedTableStyle () {
  151 + let style = {};
  152 + if (this.leftFixedColumns.length) style.width = this.leftFixedColumns.reduce((a, b) => a + b);
  153 + return style;
  154 + },
  155 + fixedRightTableStyle () {
  156 + let style = {};
  157 + if (this.rightFixedColumns.length) style.width = this.rightFixedColumns.reduce((a, b) => a + b);
  158 + return style;
  159 + },
151 160 bodyStyle () {
152 161 let style = {};
153 162 if (this.bodyHeight !== 0) style.height = `${this.bodyHeight}px`;
... ... @@ -171,7 +180,7 @@
171 180 let autoWidthIndex = -1;
172 181 if (allWidth) autoWidthIndex = this.cloneColumns.findIndex(cell => !cell.width);
173 182  
174   - const $td = this.$els.tbody.querySelectorAll('tbody tr')[0].querySelectorAll('td');
  183 + const $td = this.$refs.tbody.$el.querySelectorAll('tbody tr')[0].querySelectorAll('td');
175 184 for (let i = 0; i < $td.length; i++) { // can not use forEach in Firefox
176 185 if (i === autoWidthIndex) {
177 186 this.columnsWidth.push(parseInt(getStyle($td[i], 'width')) - 1);
... ... @@ -241,8 +250,16 @@
241 250 }
242 251 this.$emit('on-selection-change', selection);
243 252 },
244   - selectAll () {
245   - this.$emit('on-select-all', this.getSelection());
  253 + selectAll (status) {
  254 + let tmpData = deepCopy(this.cloneData);
  255 + tmpData.forEach((data) => {
  256 + data._isChecked = status;
  257 + });
  258 + this.cloneData = tmpData;
  259 +
  260 + if (status) {
  261 + this.$emit('on-select-all', this.getSelection());
  262 + }
246 263 },
247 264 fixedHeader () {
248 265 if (!!this.height) {
... ... @@ -277,8 +294,15 @@
277 294  
278 295 // todo 固定时上下滚动,固定的表头也滚动 scrollTop
279 296 },
280   - handleMouseWheel () {
281   - console.log(111)
  297 + handleMouseWheel (event) {
  298 + const deltaX = event.deltaX;
  299 + const $body = this.$els.body;
  300 +
  301 + if (deltaX > 0) {
  302 + $body.scrollLeft = $body.scrollLeft + 10;
  303 + } else {
  304 + $body.scrollLeft = $body.scrollLeft - 10;
  305 + }
282 306 }
283 307 },
284 308 compiled () {
... ...
src/styles/components/table.less
... ... @@ -10,7 +10,7 @@
10 10 border: 1px solid @border-color-base;
11 11 border-bottom: 0;
12 12 border-right: 0;
13   - border-collapse: collapse;
  13 + //border-collapse: collapse;
14 14 box-sizing: border-box;
15 15 position: relative;
16 16  
... ... @@ -130,6 +130,9 @@
130 130 word-break: break-all;
131 131 box-sizing: border-box;
132 132 }
  133 + &-hidden{
  134 + visibility: hidden;
  135 + }
133 136 th &-cell{
134 137 display: inline-block;
135 138 position: relative;
... ... @@ -186,4 +189,29 @@
186 189 background-color: @table-td-highlight-bg;
187 190 }
188 191 }
  192 +
  193 + &-fixed, &-fixed-right{
  194 + position: absolute;
  195 + top: 0;
  196 + left: 0;
  197 + box-shadow: 1px 0 8px #d3d4d6;
  198 + overflow-x: hidden;
  199 +
  200 + &::before {
  201 + content: '';
  202 + width: 100%;
  203 + height: 1px;
  204 + background-color: @border-color-base;
  205 + position: absolute;
  206 + left: 0;
  207 + bottom: 0;
  208 + z-index: 4;
  209 + }
  210 + }
  211 + &-fixed-right{
  212 + top: 0;
  213 + left: auto;
  214 + right: 0;
  215 + box-shadow: -1px 0 8px #d3d4d6;
  216 + }
189 217 }
190 218 \ No newline at end of file
... ...
test/routers/table.vue
... ... @@ -8,9 +8,8 @@
8 8 <!--<i-table size="large" border stripe :columns="columns" :data="data"></i-table>-->
9 9 <br>
10 10 <i-table
11   - style="width:450px"
  11 + width="450"
12 12 border
13   - highlight-row
14 13 :columns="columns"
15 14 :data="data"
16 15 :row-class-name="rowClsName"
... ... @@ -38,6 +37,10 @@
38 37 width: 50
39 38 },
40 39 {
  40 + type: 'index',
  41 + width: 50
  42 + },
  43 + {
41 44 title: '姓名',
42 45 key: 'name',
43 46 align: 'left',
... ... @@ -48,7 +51,7 @@
48 51 title: '年龄',
49 52 key: 'age',
50 53 align: 'right',
51   - fixed: 'left',
  54 +// fixed: 'left',
52 55 width: 100
53 56 // render (row) {
54 57 // return `<i-button>${row.age}</i-button>`
... ... @@ -142,7 +145,7 @@
142 145 },
143 146 ready () {
144 147 setTimeout(() => {
145   - return;
  148 +// return;
146 149 // this.height = 150;
147 150 // return
148 151 // this.data.push({
... ... @@ -151,7 +154,7 @@
151 154 // address: '北京市东城区2',
152 155 // edit: false
153 156 // });
154   - this.data.splice(1, 1)
  157 +// this.data.splice(1, 1)
155 158 }, 1000);
156 159 }
157 160 }
... ...