Commit b52e633ca637d904b0cddd7831b5d60437692eea
1 parent
2c334740
Exists in
master
and in
2 other branches
feat: 优化Table组件
Showing
4 changed files
with
64 additions
and
57 deletions
Show diff stats
examples/views/docs/component/table.md
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | |
| 7 | 7 | 基本参数与ElementUI的`el-table`相同。 |
| 8 | 8 | |
| 9 | -::: snippet 支持`size`继承 | |
| 9 | +::: snippet 支持来自表单的`size`继承 | |
| 10 | 10 | |
| 11 | 11 | ```html |
| 12 | 12 | <template> |
| ... | ... | @@ -44,23 +44,14 @@ export default { |
| 44 | 44 | |
| 45 | 45 | ```html |
| 46 | 46 | <template> |
| 47 | - <el-form size="mini"> | |
| 48 | - <el-row> | |
| 49 | - <el-col :span="18"> | |
| 50 | - <z-table v-model="tableData" type="editable" border :columns="columns"> | |
| 51 | - <template #column-editor-gender="{ value, onInput }"> | |
| 52 | - <el-radio-group size="mini" :value="value" @input="onInput"> | |
| 53 | - <el-radio-button label="男">男</el-radio-button> | |
| 54 | - <el-radio-button label="女">女</el-radio-button> | |
| 55 | - </el-radio-group> | |
| 56 | - </template> | |
| 57 | - </z-table> | |
| 58 | - </el-col> | |
| 59 | - <el-col :span="6" style="padding-left: 10px"> | |
| 60 | - <pre class="demo-model">{{ tableData }}</pre> | |
| 61 | - </el-col> | |
| 62 | - </el-row> | |
| 63 | - </el-form> | |
| 47 | + <z-table v-model="tableData" type="editable" border :columns="columns"> | |
| 48 | + <template #editor-gender="{ value, onInput }"> | |
| 49 | + <el-radio-group size="mini" :value="value" @input="onInput"> | |
| 50 | + <el-radio-button label="男">男</el-radio-button> | |
| 51 | + <el-radio-button label="女">女</el-radio-button> | |
| 52 | + </el-radio-group> | |
| 53 | + </template> | |
| 54 | + </z-table> | |
| 64 | 55 | </template> |
| 65 | 56 | |
| 66 | 57 | <script> |
| ... | ... | @@ -68,14 +59,15 @@ export default { |
| 68 | 59 | data() { |
| 69 | 60 | return { |
| 70 | 61 | tableData: [ |
| 71 | - { name: '张三', age: 31, gender: '男' }, | |
| 72 | - { name: '李四', age: 27, gender: '女' }, | |
| 73 | - { name: '王五', age: 16, gender: '男' }, | |
| 62 | + { name: '张三', age: 31, gender: '男', remark: '' }, | |
| 63 | + { name: '李四', age: 27, gender: '女', remark: '' }, | |
| 64 | + { name: '王五', age: 16, gender: '男', remark: '' }, | |
| 74 | 65 | ], |
| 75 | 66 | columns: [ |
| 76 | 67 | { prop: 'name', label: '姓名', editable: false }, |
| 77 | 68 | { type: 'el-input-number', prop: 'age', label: '年龄' }, |
| 78 | 69 | { prop: 'gender', label: '性别' }, |
| 70 | + { prop: 'remark', label: '备注' }, | |
| 79 | 71 | ] |
| 80 | 72 | }; |
| 81 | 73 | }, |
| ... | ... | @@ -83,4 +75,15 @@ export default { |
| 83 | 75 | </script> |
| 84 | 76 | ``` |
| 85 | 77 | |
| 86 | -::: | |
| 87 | 78 | \ No newline at end of file |
| 79 | +::: | |
| 80 | + | |
| 81 | +## API | |
| 82 | + | |
| 83 | +## Attribute 属性 | |
| 84 | + | |
| 85 | +参数|说明|类型|可选值|默认值 | |
| 86 | +-|-|-|-|- | |
| 87 | +data | 表格数据 | Array | - | - | |
| 88 | +value | 表格数据(支持v-model) | Array | - | [] | |
| 89 | +columns | 表格列配置 | Array | - | [] | |
| 90 | +type | 表格类型 | String | normal、editable | normal | |
| 88 | 91 | \ No newline at end of file | ... | ... |
packages/table/editable.vue
| ... | ... | @@ -30,23 +30,21 @@ |
| 30 | 30 | <el-table :data="tableData | tableDataFilter" :size="tableSize" v-bind="_props" @header-click="onHeaderClick" @cell-click="onCellClick" @cell-dblclick="onCellDblclick"> |
| 31 | 31 | <template v-for="(item, index) in columns"> |
| 32 | 32 | <el-table-column v-bind="item" :key="index"> |
| 33 | - <template #header> | |
| 34 | - <span>{{ item.label }}</span> | |
| 35 | - </template> | |
| 33 | + <slot :name="`header-${item.prop}`" slot="header"></slot> | |
| 36 | 34 | <template #default="{ row, column }"> |
| 37 | - <table-column-cell | |
| 38 | - :disabled="item.editable === false" | |
| 35 | + <cell-editor | |
| 36 | + :disabled="disabled || item.editable === false" | |
| 39 | 37 | :editable="item.editable !== false && (row.$editable || (tableEditCell.index === row.$index && tableEditCell.prop === item.prop))" |
| 40 | 38 | :type="item.type" |
| 41 | 39 | :value="row[column.property]" |
| 42 | 40 | @input="onCellInput" |
| 43 | - @edit-click="onCellDblclick(row, column)" | |
| 44 | - @edit-confirm="onHeaderClick" | |
| 41 | + @edit-click="setEditCell(row, column)" | |
| 42 | + @edit-confirm="cancelEditCell" | |
| 45 | 43 | > |
| 46 | - <template v-if="$scopedSlots[`column-editor-${item.prop}`]"> | |
| 47 | - <slot :name="`column-editor-${item.prop}`" :value="row[column.property]" :onInput="onCellInput"></slot> | |
| 44 | + <template v-if="$scopedSlots[`editor-${item.prop}`]"> | |
| 45 | + <slot :name="`editor-${item.prop}`" :value="row[column.property]" :onInput="onCellInput"></slot> | |
| 48 | 46 | </template> |
| 49 | - </table-column-cell> | |
| 47 | + </cell-editor> | |
| 50 | 48 | </template> |
| 51 | 49 | </el-table-column> |
| 52 | 50 | </template> |
| ... | ... | @@ -62,16 +60,12 @@ export default { |
| 62 | 60 | name: 'TableEditable', |
| 63 | 61 | extends: TableNormal, |
| 64 | 62 | components: { |
| 65 | - tableColumnCell: { | |
| 63 | + cellEditor: { | |
| 66 | 64 | props: { |
| 67 | 65 | value: [String, Number, Array, Object], |
| 68 | 66 | type: { type: String, default: 'el-input' }, |
| 69 | 67 | editable: Boolean, |
| 70 | 68 | disabled: Boolean, |
| 71 | - showHandler: { | |
| 72 | - type: Boolean, | |
| 73 | - default: true, | |
| 74 | - }, | |
| 75 | 69 | }, |
| 76 | 70 | watch: { |
| 77 | 71 | editable(val) { |
| ... | ... | @@ -84,7 +78,7 @@ export default { |
| 84 | 78 | }, |
| 85 | 79 | render(h) { |
| 86 | 80 | if (this.editable) { |
| 87 | - let editRender = [ | |
| 81 | + let editorRender = [ | |
| 88 | 82 | h(this.type, { |
| 89 | 83 | props: { value: this.value, size: 'mini' }, |
| 90 | 84 | on: { |
| ... | ... | @@ -95,21 +89,21 @@ export default { |
| 95 | 89 | }), |
| 96 | 90 | ]; |
| 97 | 91 | if (this.$scopedSlots.default) { |
| 98 | - editRender = [this.$scopedSlots.default()]; | |
| 92 | + editorRender = [this.$scopedSlots.default()]; | |
| 99 | 93 | } |
| 100 | - if (this.showHandler !== false) { | |
| 94 | + if (!this.disabled) { | |
| 101 | 95 | const handlerItems = [h('i', { attrs: { title: '确定', class: 'el-icon-check' }, on: { click: () => this.$emit('edit-confirm') } })]; |
| 102 | 96 | // handlerItems.push(h('i', { attrs: { title: '取消', class: 'el-icon-close' }, on: { click: () => this.$emit('edit-confirm') } })); |
| 103 | 97 | const handler = h('span', handlerItems); |
| 104 | - editRender.push(handler); | |
| 98 | + editorRender.push(handler); | |
| 105 | 99 | } |
| 106 | - return h('span', { class: 'z-table-column__cell-editable' }, editRender); | |
| 100 | + return h('span', { class: 'z-table-column__cell-editable' }, editorRender); | |
| 107 | 101 | } |
| 108 | - const defauleRender = [this.value]; | |
| 109 | - if (!this.disabled && this.showHandler !== false) { | |
| 110 | - defauleRender.push(h('i', { attrs: { title: '编辑', class: 'el-icon-edit' }, on: { click: () => this.$emit('edit-click') } })); | |
| 102 | + const valueRender = [h('span', this.value)]; | |
| 103 | + if (!this.disabled) { | |
| 104 | + valueRender.push(h('i', { attrs: { title: '编辑', class: 'el-icon-edit' }, on: { click: () => this.$emit('edit-click') } })); | |
| 111 | 105 | } |
| 112 | - return h('span', { class: 'z-table-column__cell-editable' }, defauleRender); | |
| 106 | + return h('span', { class: 'z-table-column__cell-editable' }, valueRender); | |
| 113 | 107 | }, |
| 114 | 108 | }, |
| 115 | 109 | }, |
| ... | ... | @@ -126,6 +120,8 @@ export default { |
| 126 | 120 | return []; |
| 127 | 121 | }, |
| 128 | 122 | }, |
| 123 | + clickable: Boolean, | |
| 124 | + disabled: Boolean, | |
| 129 | 125 | ...tableProps, |
| 130 | 126 | }, |
| 131 | 127 | watch: { |
| ... | ... | @@ -146,21 +142,30 @@ export default { |
| 146 | 142 | return value.map((item, index) => ({ ...item, $index: index })); |
| 147 | 143 | }, |
| 148 | 144 | }, |
| 149 | - // mounted() { | |
| 150 | - // console.log(this.$scopedSlots); | |
| 151 | - // }, | |
| 152 | 145 | methods: { |
| 153 | 146 | onHeaderClick() { |
| 154 | - this.tableEditCell = {}; | |
| 147 | + if (this.clickable) { | |
| 148 | + this.cancelEditCell(); | |
| 149 | + } | |
| 155 | 150 | }, |
| 156 | - onCellClick(row, column, cell, event) { | |
| 157 | - if (row.$index !== this.tableEditCell.index || column.property !== this.tableEditCell.prop) { | |
| 158 | - this.tableEditCell = {}; | |
| 151 | + onCellClick(row, column) { | |
| 152 | + if (this.clickable) { | |
| 153 | + if (row.$index !== this.tableEditCell.index || column.property !== this.tableEditCell.prop) { | |
| 154 | + this.tableEditCell = {}; | |
| 155 | + } | |
| 159 | 156 | } |
| 160 | 157 | }, |
| 161 | - onCellDblclick(row, column, cell, event) { | |
| 158 | + onCellDblclick(row, column) { | |
| 159 | + if (this.clickable) { | |
| 160 | + this.setEditCell(row, column); | |
| 161 | + } | |
| 162 | + }, | |
| 163 | + setEditCell(row, column) { | |
| 162 | 164 | this.tableEditCell = { index: row.$index, prop: column.property }; |
| 163 | 165 | }, |
| 166 | + cancelEditCell() { | |
| 167 | + this.tableEditCell = {}; | |
| 168 | + }, | |
| 164 | 169 | onCellInput(value) { |
| 165 | 170 | const tableData = cloneDeep(this.tableData); |
| 166 | 171 | const tableRow = tableData[this.tableEditCell.index]; | ... | ... |
packages/table/index.js
packages/table/normal.vue