commit Table component
commit Table component
This commit is contained in:
parent
d2e82cd7f6
commit
2cb8a6d93e
12 changed files with 334 additions and 0 deletions
2
src/components/table/index.js
Normal file
2
src/components/table/index.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import Table from './table.vue';
|
||||||
|
export default Table;
|
21
src/components/table/table-body.vue
Normal file
21
src/components/table/table-body.vue
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
21
src/components/table/table-column.vue
Normal file
21
src/components/table/table-column.vue
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
32
src/components/table/table-head.vue
Normal file
32
src/components/table/table-head.vue
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<template>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="column in columns">{{{ renderHeader(column, $index) }}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
prefixCls: String,
|
||||||
|
columns: Array
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
renderHeader (column, $index) {
|
||||||
|
if ('renderHeader' in this.columns[$index]) {
|
||||||
|
return this.columns[$index].renderHeader(column, $index);
|
||||||
|
} else {
|
||||||
|
return column.title || '#';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
149
src/components/table/table.vue
Normal file
149
src/components/table/table.vue
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
<template>
|
||||||
|
<div :class="classes">
|
||||||
|
<div :class="[prefixCls + '-body']">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col v-for="column in columns" :width="column.width">
|
||||||
|
</colgroup>
|
||||||
|
<thead
|
||||||
|
is="table-head"
|
||||||
|
:prefix-cls="prefixCls + '-thead'"
|
||||||
|
:columns="columns"></thead>
|
||||||
|
<tbody :class="[prefixCls + '-tbody']" v-el:render>
|
||||||
|
<tr :class="[prefixCls + '-row']" v-for="(index, row) in data">
|
||||||
|
<td v-for="column in columns">{{{ renderRow(row, column) }}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import TableHead from './table-head.vue';
|
||||||
|
import { oneOf } from '../../utils/assist';
|
||||||
|
const prefixCls = 'ivu-table';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { TableHead },
|
||||||
|
props: {
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
validator (value) {
|
||||||
|
return oneOf(value, ['small', 'large']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stripe: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
fit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showHeader: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
validator (value) {
|
||||||
|
return oneOf(value, ['single', 'multiple', false]);
|
||||||
|
},
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showIndex: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
prefixCls: prefixCls,
|
||||||
|
compiledUids: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
classes () {
|
||||||
|
return [
|
||||||
|
`${prefixCls}`,
|
||||||
|
{
|
||||||
|
[`${prefixCls}-${this.size}`]: !!this.size
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
renderRow (row, column) {
|
||||||
|
return 'render' in column ? '' : row[column.key];
|
||||||
|
},
|
||||||
|
compileRender (update = false) {
|
||||||
|
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 $el = this.$els.render;
|
||||||
|
for (let i = 0; i < this.columns.length; i++) {
|
||||||
|
const column = this.columns[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].innerHTML = '';
|
||||||
|
$el.children[j].children[i].appendChild(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ready () {
|
||||||
|
this.compileRender();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
data: {
|
||||||
|
handler () {
|
||||||
|
this.compileRender(true);
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
handler () {
|
||||||
|
this.compileRender(true);
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -12,6 +12,7 @@
|
||||||
import iInput from '../input/input.vue';
|
import iInput from '../input/input.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { iInput },
|
||||||
props: {
|
props: {
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
|
|
|
@ -24,6 +24,7 @@ import Slider from './components/slider';
|
||||||
import Spin from './components/spin';
|
import Spin from './components/spin';
|
||||||
import Steps from './components/steps';
|
import Steps from './components/steps';
|
||||||
import Switch from './components/switch';
|
import Switch from './components/switch';
|
||||||
|
import Table from './components/table';
|
||||||
import Tag from './components/tag';
|
import Tag from './components/tag';
|
||||||
import Timeline from './components/timeline';
|
import Timeline from './components/timeline';
|
||||||
import Tooltip from './components/tooltip';
|
import Tooltip from './components/tooltip';
|
||||||
|
@ -69,6 +70,7 @@ const iview = {
|
||||||
Step: Steps.Step,
|
Step: Steps.Step,
|
||||||
Steps,
|
Steps,
|
||||||
Switch,
|
Switch,
|
||||||
|
iTable: Table,
|
||||||
Tag,
|
Tag,
|
||||||
Timeline,
|
Timeline,
|
||||||
TimelineItem: Timeline.Item,
|
TimelineItem: Timeline.Item,
|
||||||
|
|
0
src/styles/components/table.less
Normal file
0
src/styles/components/table.less
Normal file
|
@ -75,4 +75,16 @@ export function getStyle (element, styleName) {
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return element.style[styleName];
|
return element.style[styleName];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// firstUpperCase
|
||||||
|
function firstUpperCase(str) {
|
||||||
|
return str.toString()[0].toUpperCase() + str.toString().slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn
|
||||||
|
export function warnProp(component, prop, correctType, wrongType) {
|
||||||
|
correctType = firstUpperCase(correctType);
|
||||||
|
wrongType = firstUpperCase(wrongType);
|
||||||
|
console.error(`[iView warn]: Invalid prop: type check failed for prop ${prop}. Expected ${correctType}, got ${wrongType}. (found in component: ${component})`);
|
||||||
}
|
}
|
|
@ -41,6 +41,7 @@ li + li {
|
||||||
<li><a v-link="'/input'">Input</a></li>
|
<li><a v-link="'/input'">Input</a></li>
|
||||||
<li><a v-link="'/cascader'">Cascader</a></li>
|
<li><a v-link="'/cascader'">Cascader</a></li>
|
||||||
<li><a v-link="'/transfer'">Transfer</a></li>
|
<li><a v-link="'/transfer'">Transfer</a></li>
|
||||||
|
<li><a v-link="'/table'">Table</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
|
|
|
@ -102,6 +102,11 @@ router.map({
|
||||||
component: function (resolve) {
|
component: function (resolve) {
|
||||||
require(['./routers/transfer.vue'], resolve);
|
require(['./routers/transfer.vue'], resolve);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'/table': {
|
||||||
|
component: function (resolve) {
|
||||||
|
require(['./routers/table.vue'], resolve);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
88
test/routers/table.vue
Normal file
88
test/routers/table.vue
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<i-table :columns="columns" :data="data"></i-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
key: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '年龄',
|
||||||
|
key: 'age',
|
||||||
|
// render (row) {
|
||||||
|
// return `<i-button>${row.age}</i-button>`
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
key: 'address',
|
||||||
|
// render (row, column, index) {
|
||||||
|
// if (row.edit) {
|
||||||
|
// return `<i-input :value.sync="data[${index}].name"></i-input>`;
|
||||||
|
// } else {
|
||||||
|
// return `<Tooltip content="${row.address}"><i-button @click="show(${index})">${row.name}</i-button></Tooltip>`;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
render (row, column, index) {
|
||||||
|
return `<i-button @click="edit(${index})">编辑</i-button>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
name: '梁灏',
|
||||||
|
age: 25,
|
||||||
|
address: '北京市朝阳区',
|
||||||
|
edit: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '段模',
|
||||||
|
age: 26,
|
||||||
|
address: '北京市海淀区',
|
||||||
|
edit: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '刘天娇',
|
||||||
|
age: 27,
|
||||||
|
address: '北京市东城区',
|
||||||
|
edit: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
show (name) {
|
||||||
|
this.$Message.info(name);
|
||||||
|
},
|
||||||
|
edit (index) {
|
||||||
|
this.data[index].edit = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ready () {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.data.push({
|
||||||
|
name: '刘天娇2',
|
||||||
|
age: 272,
|
||||||
|
address: '北京市东城区2',
|
||||||
|
edit: false
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Add table
Reference in a new issue