diff --git a/src/components/table/cell.vue b/src/components/table/cell.vue new file mode 100644 index 0000000..1fa8a1f --- /dev/null +++ b/src/components/table/cell.vue @@ -0,0 +1,68 @@ +<template> + <div :class="[prefixCls + '-cell']"> + <template v-if="renderType === 'index'">{{index + 1}}</template> + <template v-if="renderType === 'normal'">{{{ row[column.key] }}}</template> + </div> +</template> +<script> + export default { + props: { + prefixCls: String, + row: Object, + column: Object, + index: Number + }, + data () { + return { + renderType: '', + uid: -1 + } + }, + methods: { + compile () { + if (this.column.render) { + const template = this.column.render(this.row, this.column, this.index); + const cell = document.createElement('div'); + cell.innerHTML = template; + const _oldParentChildLen = this.$parent.$parent.$children.length; + this.$parent.$parent.$compile(cell); + const _newParentChildLen = this.$parent.$parent.$children.length; + + if (_oldParentChildLen !== _newParentChildLen) { // if render normal html node, do not tag + this.uid = this.$parent.$parent.$children[this.$parent.$parent.$children.length - 1]._uid; // tag it, and delete when data or columns update + } + this.$el.innerHTML = ''; + this.$el.appendChild(cell); + } + }, + destroy () { + for (let i = 0; i < this.$parent.$parent.$children.length; i++) { + if (this.$parent.$parent.$children[i]._uid === this.uid) { + this.$parent.$parent.$children[i].$destroy(); + } + } + } + }, + compiled () { + if (this.column.type === 'index') { + this.renderType = 'index'; + } else if (this.column.render) { + this.renderType = 'render'; + } else { + this.renderType = 'normal'; + } + }, + ready () { + this.compile(); + }, + beforeDestroy () { + this.destroy(); + }, + watch: { + index () { + this.destroy(); + this.compile(); + } + } + } +</script> \ No newline at end of file diff --git a/src/components/table/table.vue b/src/components/table/table.vue index c416f77..efc7b05 100644 --- a/src/components/table/table.vue +++ b/src/components/table/table.vue @@ -26,12 +26,19 @@ @mouseleave.stop="handleMouseOut(index)" @click.stop="highlightCurrentRow(index)"> <td v-for="column in cloneColumns" :class="alignCls(column)"> - <div :class="[prefixCls + '-cell']"> - <template v-if="column.type === 'selection'"> - <Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox> - </template> - <template v-else>{{{ renderRow(row, column, index) }}}</template> + <div :class="[prefixCls + '-cell']" v-if="column.type === 'selection'"> + <Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox> </div> + <Cell v-else :prefix-cls="prefixCls" :row="row" :column="column" :index="index"></Cell> + <!--<div :class="[prefixCls + '-cell']" v-else>--> + <!--{{{ renderRow(row, column, index) }}}--> + <!--</div>--> + <!--<div :class="[prefixCls + '-cell']">--> + <!--<template v-if="column.type === 'selection'">--> + <!--<Checkbox :checked="cloneData[index] && cloneData[index]._isChecked" @on-change="toggleSelect(index)"></Checkbox>--> + <!--</template>--> + <!--<template v-else>{{{ renderRow(row, column, index) }}}</template>--> + <!--</div>--> </td> </tr> </tbody> @@ -49,13 +56,14 @@ <script> import TableHead from './table-head.vue'; import Checkbox from '../checkbox/checkbox.vue'; + import Cell from './cell.vue'; import Mixin from './mixin'; import { oneOf, getStyle, deepCopy } from '../../utils/assist'; const prefixCls = 'ivu-table'; export default { mixins: [ Mixin ], - components: { TableHead, Checkbox }, + components: { TableHead, Checkbox, Cell }, props: { data: { type: Array, @@ -108,6 +116,9 @@ compiledUids: [], cloneData: deepCopy(this.data), cloneColumns: deepCopy(this.columns), + leftFixedColumns: [], + rightFixedColumns: [], + centerColumns: [], showSlotHeader: true, showSlotFooter: true, bodyHeight: 0 @@ -147,53 +158,25 @@ rowClsName (index) { return this.rowClassName(this.data[index], index); }, - renderRow (row, column, index) { - return column.type === 'index' ? index + 1 : column.render ? '' : row[column.key]; - }, - compileRender (update = false) { + handleResize () { this.$nextTick(() => { - if (update) { - for (let i = 0; i < this.$parent.$children.length; i++) { - const index = this.compiledUids.indexOf(this.$parent.$children[i]._uid); - if (index > -1) { - this.$parent.$children[i].$destroy(); - this.compiledUids.splice(index, 1); - i--; - } - } + const allWidth = !this.columns.some(cell => !cell.width); + if (allWidth) { + this.tableWidth = this.columns.map(cell => cell.width).reduce((a, b) => a + b); + } else { + this.tableWidth = parseInt(getStyle(this.$el, 'width')) - 1; } - - const $el = this.$els.render; - for (let i = 0; i < this.cloneColumns.length; i++) { - const column = this.cloneColumns[i]; - if (column.render) { - for (let j = 0; j < this.data.length; j++) { - // todo 做一个缓存,只在需要改render时再重新编译,data改变时不用再编译 - const row = this.data[j]; - const template = column.render(row, column, j); - const cell = document.createElement('div'); - cell.innerHTML = template; - const _oldParentChildLen = this.$parent.$children.length; - this.$parent.$compile(cell); - const _newParentChildLen = this.$parent.$children.length; - - if (_oldParentChildLen !== _newParentChildLen) { // if render normal html node, do not tag - this.compiledUids.push(this.$parent.$children[this.$parent.$children.length - 1]._uid); // tag it, and delete when data or columns update - } - $el.children[j].children[i].children[0].innerHTML = ''; - $el.children[j].children[i].children[0].appendChild(cell); + this.$nextTick(() => { + this.columnsWidth = []; + let autoWidthIndex = -1 + if (allWidth) autoWidthIndex = this.cloneColumns.findIndex(cell => !cell.width); + this.$els.tbody.querySelectorAll('tbody tr')[0].querySelectorAll('td').forEach((cell, index) => { + if (index === autoWidthIndex) { + this.columnsWidth.push(parseInt(getStyle(cell, 'width')) - 1); + } else { + this.columnsWidth.push(parseInt(getStyle(cell, 'width'))); } - } - } - this.handleResize(); - }); - }, - handleResize () { - this.tableWidth = parseInt(getStyle(this.$el, 'width')); - this.$nextTick(() => { - this.columnsWidth = []; - this.$els.tbody.querySelectorAll('tbody tr')[0].querySelectorAll('td').forEach((cell) => { - this.columnsWidth.push(parseInt(getStyle(cell, 'width'))); + }); }); }); }, @@ -282,6 +265,9 @@ center.push(col); } }); + this.leftFixedColumns = left; + this.rightFixedColumns = right; + this.centerColumns = center; this.cloneColumns = left.concat(center).concat(right); } }, @@ -291,7 +277,7 @@ this.showSlotFooter = this.$els.footer.innerHTML.replace(/\n/g, '').replace(/<!--[\w\W\r\n]*?-->/gmi, '') !== ''; }, ready () { - this.compileRender(); + this.handleResize(); this.fixedHeader(); window.addEventListener('resize', this.handleResize, false); }, @@ -302,14 +288,14 @@ data: { handler () { this.cloneData = deepCopy(this.data); - this.compileRender(true); + this.handleResize(); }, deep: true }, columns: { handler () { this.parseColumns(); - this.compileRender(true); + this.handleResize(); }, deep: true }, diff --git a/src/styles/components/table.less b/src/styles/components/table.less index f8d35df..30f0c83 100644 --- a/src/styles/components/table.less +++ b/src/styles/components/table.less @@ -9,10 +9,33 @@ background-color: #fff; border: 1px solid @border-color-base; border-bottom: 0; + border-right: 0; border-collapse: collapse; box-sizing: border-box; position: relative; + &:before{ + content: ''; + width: 100%; + height: 1px; + position: absolute; + left: 0; + bottom: 0; + background-color: @border-color-base; + z-index: 1; + } + + &:after{ + content: ''; + width: 1px; + height: 100%; + position: absolute; + top: 0; + right: 0; + background-color: @border-color-base; + z-index: 1; + } + &-with-header{ border-radius: @border-radius-base @border-radius-base 0 0; } @@ -36,8 +59,9 @@ } &-body{ - overflow-x: hidden; - overflow-y: auto; + //overflow-x: hidden; + //overflow-y: auto; + overflow: auto; position: relative; } @@ -91,7 +115,8 @@ } & table{ - width: 100%; + //width: 100%; + table-layout: fixed; } &-border{ th,td{ diff --git a/test/routers/table.vue b/test/routers/table.vue index b1af924..7be2d62 100644 --- a/test/routers/table.vue +++ b/test/routers/table.vue @@ -8,6 +8,7 @@ <!--<i-table size="large" border stripe :columns="columns" :data="data"></i-table>--> <br> <i-table + style="width:450px" border highlight-row :columns="columns" @@ -57,7 +58,7 @@ title: '地址', key: 'address', align: 'center', -// width: 100 + width: 100, // render (row, column, index) { // if (row.edit) { // return `<i-input :value.sync="data[${index}].name"></i-input>`; @@ -72,7 +73,8 @@ fixed: 'right', width: 200, render (row, column, index) { - return `<i-button @click="edit(${index})">编辑</i-button>` + return `<i-button @click="edit(${index})">${row.name}</i-button>` +// return `<a>${row.name}</a>` } } ], @@ -140,14 +142,16 @@ }, ready () { setTimeout(() => { + return; // this.height = 150; - return - this.data.push({ - name: '刘天娇2', - age: 272, - address: '北京市东城区2', - edit: false - }); +// return +// this.data.push({ +// name: '刘天娇2', +// age: 272, +// address: '北京市东城区2', +// edit: false +// }); + this.data.splice(1, 1) }, 1000); } } -- libgit2 0.21.4