Commit 2cb8a6d93e7705490f5045e737a292360505a0ce

Authored by 梁灏
1 parent d2e82cd7

commit Table component

commit Table component
src/components/table/index.js 0 → 100644
  1 +import Table from './table.vue';
  2 +export default Table;
0 3 \ No newline at end of file
... ...
src/components/table/table-body.vue 0 → 100644
  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>
0 22 \ No newline at end of file
... ...
src/components/table/table-column.vue 0 → 100644
  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>
0 22 \ No newline at end of file
... ...
src/components/table/table-head.vue 0 → 100644
  1 +<template>
  2 + <thead>
  3 + <tr>
  4 + <th v-for="column in columns">{{{ renderHeader(column, $index) }}}</th>
  5 + </tr>
  6 + </thead>
  7 +</template>
  8 +<script>
  9 + export default {
  10 + props: {
  11 + prefixCls: String,
  12 + columns: Array
  13 + },
  14 + data () {
  15 + return {
  16 +
  17 + }
  18 + },
  19 + computed: {
  20 +
  21 + },
  22 + methods: {
  23 + renderHeader (column, $index) {
  24 + if ('renderHeader' in this.columns[$index]) {
  25 + return this.columns[$index].renderHeader(column, $index);
  26 + } else {
  27 + return column.title || '#';
  28 + }
  29 + }
  30 + }
  31 + }
  32 +</script>
0 33 \ No newline at end of file
... ...
src/components/table/table.vue 0 → 100644
  1 +<template>
  2 + <div :class="classes">
  3 + <div :class="[prefixCls + '-body']">
  4 + <table>
  5 + <colgroup>
  6 + <col v-for="column in columns" :width="column.width">
  7 + </colgroup>
  8 + <thead
  9 + is="table-head"
  10 + :prefix-cls="prefixCls + '-thead'"
  11 + :columns="columns"></thead>
  12 + <tbody :class="[prefixCls + '-tbody']" v-el:render>
  13 + <tr :class="[prefixCls + '-row']" v-for="(index, row) in data">
  14 + <td v-for="column in columns">{{{ renderRow(row, column) }}}</td>
  15 + </tr>
  16 + </tbody>
  17 + </table>
  18 + </div>
  19 + </div>
  20 +</template>
  21 +<script>
  22 + import TableHead from './table-head.vue';
  23 + import { oneOf } from '../../utils/assist';
  24 + const prefixCls = 'ivu-table';
  25 +
  26 + export default {
  27 + components: { TableHead },
  28 + props: {
  29 + data: {
  30 + type: Array,
  31 + default () {
  32 + return []
  33 + }
  34 + },
  35 + columns: {
  36 + type: Array,
  37 + default () {
  38 + return []
  39 + }
  40 + },
  41 + size: {
  42 + validator (value) {
  43 + return oneOf(value, ['small', 'large']);
  44 + }
  45 + },
  46 + stripe: {
  47 + type: Boolean,
  48 + default: false
  49 + },
  50 + border: {
  51 + type: Boolean,
  52 + default: false
  53 + },
  54 + fit: {
  55 + type: Boolean,
  56 + default: true
  57 + },
  58 + showHeader: {
  59 + type: Boolean,
  60 + default: true
  61 + },
  62 + selection: {
  63 + validator (value) {
  64 + return oneOf(value, ['single', 'multiple', false]);
  65 + },
  66 + default: false
  67 + },
  68 + showIndex: {
  69 + type: Boolean,
  70 + default: false
  71 + }
  72 + },
  73 + data () {
  74 + return {
  75 + prefixCls: prefixCls,
  76 + compiledUids: []
  77 + }
  78 + },
  79 + computed: {
  80 + classes () {
  81 + return [
  82 + `${prefixCls}`,
  83 + {
  84 + [`${prefixCls}-${this.size}`]: !!this.size
  85 + }
  86 + ]
  87 + }
  88 + },
  89 + methods: {
  90 + renderRow (row, column) {
  91 + return 'render' in column ? '' : row[column.key];
  92 + },
  93 + compileRender (update = false) {
  94 + this.$nextTick(() => {
  95 + if (update) {
  96 + for (let i = 0; i < this.$parent.$children.length; i++) {
  97 + const index = this.compiledUids.indexOf(this.$parent.$children[i]._uid);
  98 + if (index > -1) {
  99 + this.$parent.$children[i].$destroy();
  100 + this.compiledUids.splice(index, 1);
  101 + i--;
  102 + }
  103 + }
  104 + }
  105 +
  106 + const $el = this.$els.render;
  107 + for (let i = 0; i < this.columns.length; i++) {
  108 + const column = this.columns[i];
  109 + if (column.render) {
  110 + for (let j = 0; j < this.data.length; j++) {
  111 + // todo 做一个深度缓存,只在需要改render时再重新编译,否则data改变时不用再编译
  112 + const row = this.data[j];
  113 + const template = column.render(row, column, j);
  114 + const cell = document.createElement('div');
  115 + cell.innerHTML = template;
  116 + const _oldParentChildLen = this.$parent.$children.length;
  117 + this.$parent.$compile(cell);
  118 + const _newParentChildLen = this.$parent.$children.length;
  119 +
  120 + if (_oldParentChildLen !== _newParentChildLen) { // if render normal html node, do not tag
  121 + this.compiledUids.push(this.$parent.$children[this.$parent.$children.length - 1]._uid); // tag it, and delete when data or columns update
  122 + }
  123 + $el.children[j].children[i].innerHTML = '';
  124 + $el.children[j].children[i].appendChild(cell);
  125 + }
  126 + }
  127 + }
  128 + });
  129 + }
  130 + },
  131 + ready () {
  132 + this.compileRender();
  133 + },
  134 + watch: {
  135 + data: {
  136 + handler () {
  137 + this.compileRender(true);
  138 + },
  139 + deep: true
  140 + },
  141 + columns: {
  142 + handler () {
  143 + this.compileRender(true);
  144 + },
  145 + deep: true
  146 + }
  147 + }
  148 + }
  149 +</script>
0 150 \ No newline at end of file
... ...
src/components/transfer/search.vue
... ... @@ -12,6 +12,7 @@
12 12 import iInput from '../input/input.vue';
13 13  
14 14 export default {
  15 + components: { iInput },
15 16 props: {
16 17 prefixCls: String,
17 18 placeholder: String,
... ...
src/index.js
... ... @@ -24,6 +24,7 @@ import Slider from &#39;./components/slider&#39;;
24 24 import Spin from './components/spin';
25 25 import Steps from './components/steps';
26 26 import Switch from './components/switch';
  27 +import Table from './components/table';
27 28 import Tag from './components/tag';
28 29 import Timeline from './components/timeline';
29 30 import Tooltip from './components/tooltip';
... ... @@ -69,6 +70,7 @@ const iview = {
69 70 Step: Steps.Step,
70 71 Steps,
71 72 Switch,
  73 + iTable: Table,
72 74 Tag,
73 75 Timeline,
74 76 TimelineItem: Timeline.Item,
... ...
src/styles/components/table.less 0 → 100644
src/utils/assist.js
... ... @@ -75,4 +75,16 @@ export function getStyle (element, styleName) {
75 75 } catch(e) {
76 76 return element.style[styleName];
77 77 }
  78 +}
  79 +
  80 +// firstUpperCase
  81 +function firstUpperCase(str) {
  82 + return str.toString()[0].toUpperCase() + str.toString().slice(1);
  83 +}
  84 +
  85 +// Warn
  86 +export function warnProp(component, prop, correctType, wrongType) {
  87 + correctType = firstUpperCase(correctType);
  88 + wrongType = firstUpperCase(wrongType);
  89 + console.error(`[iView warn]: Invalid prop: type check failed for prop ${prop}. Expected ${correctType}, got ${wrongType}. (found in component: ${component})`);
78 90 }
79 91 \ No newline at end of file
... ...
test/app.vue
... ... @@ -41,6 +41,7 @@ li + li {
41 41 <li><a v-link="'/input'">Input</a></li>
42 42 <li><a v-link="'/cascader'">Cascader</a></li>
43 43 <li><a v-link="'/transfer'">Transfer</a></li>
  44 + <li><a v-link="'/table'">Table</a></li>
44 45 </ul>
45 46 </nav>
46 47 <router-view></router-view>
... ...
test/main.js
... ... @@ -102,6 +102,11 @@ router.map({
102 102 component: function (resolve) {
103 103 require(['./routers/transfer.vue'], resolve);
104 104 }
  105 + },
  106 + '/table': {
  107 + component: function (resolve) {
  108 + require(['./routers/table.vue'], resolve);
  109 + }
105 110 }
106 111 });
107 112  
... ...
test/routers/table.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <i-table :columns="columns" :data="data"></i-table>
  4 + </div>
  5 +</template>
  6 +<script>
  7 + export default {
  8 + props: {
  9 +
  10 + },
  11 + data () {
  12 + return {
  13 + columns: [
  14 + {
  15 + title: '姓名',
  16 + key: 'name'
  17 + },
  18 + {
  19 + title: '年龄',
  20 + key: 'age',
  21 +// render (row) {
  22 +// return `<i-button>${row.age}</i-button>`
  23 +// }
  24 + },
  25 + {
  26 + title: '地址',
  27 + key: 'address',
  28 +// render (row, column, index) {
  29 +// if (row.edit) {
  30 +// return `<i-input :value.sync="data[${index}].name"></i-input>`;
  31 +// } else {
  32 +// return `<Tooltip content="${row.address}"><i-button @click="show(${index})">${row.name}</i-button></Tooltip>`;
  33 +// }
  34 +// }
  35 + },
  36 + {
  37 + title: '操作',
  38 + key: 'action',
  39 + render (row, column, index) {
  40 + return `<i-button @click="edit(${index})">编辑</i-button>`
  41 + }
  42 + }
  43 + ],
  44 + data: [
  45 + {
  46 + name: '梁灏',
  47 + age: 25,
  48 + address: '北京市朝阳区',
  49 + edit: false
  50 + },
  51 + {
  52 + name: '段模',
  53 + age: 26,
  54 + address: '北京市海淀区',
  55 + edit: false
  56 + },
  57 + {
  58 + name: '刘天娇',
  59 + age: 27,
  60 + address: '北京市东城区',
  61 + edit: true
  62 + }
  63 + ]
  64 + }
  65 + },
  66 + computed: {
  67 +
  68 + },
  69 + methods: {
  70 + show (name) {
  71 + this.$Message.info(name);
  72 + },
  73 + edit (index) {
  74 + this.data[index].edit = true;
  75 + }
  76 + },
  77 + ready () {
  78 + setTimeout(() => {
  79 + this.data.push({
  80 + name: '刘天娇2',
  81 + age: 272,
  82 + address: '北京市东城区2',
  83 + edit: false
  84 + });
  85 + }, 1000);
  86 + }
  87 + }
  88 +</script>
0 89 \ No newline at end of file
... ...