Commit 52a3208c9c7bd5ef3a634be490df5af0f2d334bc
1 parent
b52e633c
Exists in
master
and in
2 other branches
feat: 优化Table组件更新文档
Showing
11 changed files
with
523 additions
and
121 deletions
Show diff stats
examples/mixins/origin.js
| @@ -46,5 +46,12 @@ export default { | @@ -46,5 +46,12 @@ export default { | ||
| 46 | } | 46 | } |
| 47 | return newObj; | 47 | return newObj; |
| 48 | }, | 48 | }, |
| 49 | + // 获取初始值 | ||
| 50 | + getOriginData(key) { | ||
| 51 | + if (key) { | ||
| 52 | + return this.cloneDeep(this.originData)[key]; | ||
| 53 | + } | ||
| 54 | + return this.cloneDeep(this.originData); | ||
| 55 | + }, | ||
| 49 | }, | 56 | }, |
| 50 | }; | 57 | }; |
examples/mixins/page.js
| 1 | -import MIX_TOAST from '@/mixins/toast'; | ||
| 2 | -import MIX_ORIGIN from '@/mixins/origin'; | 1 | +import MIX_ORIGIN from '@/mixins/origin'; // 初始值逻辑混入 |
| 3 | 2 | ||
| 4 | export default { | 3 | export default { |
| 5 | - mixins: [MIX_TOAST, MIX_ORIGIN], | 4 | + mixins: [MIX_ORIGIN], |
| 6 | data() { | 5 | data() { |
| 7 | return { | 6 | return { |
| 8 | - auto: true, | ||
| 9 | - tableData: [], | ||
| 10 | - loading: false, | ||
| 11 | - total: 0, | ||
| 12 | - currentPage: 1, | ||
| 13 | - pageSize: 10, | ||
| 14 | - pageSizes: [10, 20, 50, 100], | ||
| 15 | - layout: 'total, sizes, prev, pager, next, jumper', | ||
| 16 | - searchModel: {}, | ||
| 17 | - form: {}, | ||
| 18 | - submitting: false, | ||
| 19 | - selection: [], | 7 | + auto: true, // 页面加载时自动查询 |
| 8 | + tableData: [], // 表格数据 | ||
| 9 | + loading: false, // 加载状态 | ||
| 10 | + total: 0, // 数据总量 | ||
| 11 | + currentPage: 1, // 当前页码 | ||
| 12 | + pageSize: 10, // 分页大小 | ||
| 13 | + pageSizes: [10, 20, 50, 100], // 分页大小选项 | ||
| 14 | + layout: 'total, sizes, prev, pager, next, jumper', // 分页器默认设置 | ||
| 15 | + searchModel: {}, // 搜索表单绑定值 | ||
| 16 | + form: {}, // 常规表单绑定值 | ||
| 17 | + submitting: false, // 提交状态 | ||
| 18 | + selection: [], // 表格选中项 | ||
| 20 | collapsed: false, // 展开状态 | 19 | collapsed: false, // 展开状态 |
| 21 | }; | 20 | }; |
| 22 | }, | 21 | }, |
| @@ -94,8 +93,7 @@ export default { | @@ -94,8 +93,7 @@ export default { | ||
| 94 | this.loading = true; | 93 | this.loading = true; |
| 95 | const params = { | 94 | const params = { |
| 96 | ...this.searchModel, | 95 | ...this.searchModel, |
| 97 | - currentPage: this.currentPage, | ||
| 98 | - pageSize: this.pageSize, | 96 | + ...this.pageParams, |
| 99 | }; | 97 | }; |
| 100 | const searchAPI = this.searchAPI || this.emptyPromise; | 98 | const searchAPI = this.searchAPI || this.emptyPromise; |
| 101 | await searchAPI(params) | 99 | await searchAPI(params) |
examples/mixins/toast.js
examples/router/routes.js
| @@ -114,13 +114,13 @@ _components.forEach(data => { | @@ -114,13 +114,13 @@ _components.forEach(data => { | ||
| 114 | 114 | ||
| 115 | const _develops = [ | 115 | const _develops = [ |
| 116 | { | 116 | { |
| 117 | - group: '开发模式', | 117 | + group: '混入开发', |
| 118 | children: [ | 118 | children: [ |
| 119 | { | 119 | { |
| 120 | - path: 'mixin', | ||
| 121 | - name: 'mixin', | ||
| 122 | - meta: { title: 'Mixin 混入' }, | ||
| 123 | - component: () => import('@/views/docs/develop/mixin.md'), | 120 | + path: 'page', |
| 121 | + name: 'page', | ||
| 122 | + meta: { title: 'Mixin Page 标准页' }, | ||
| 123 | + component: () => import('@/views/docs/develop/mixin/page.md'), | ||
| 124 | }, | 124 | }, |
| 125 | ], | 125 | ], |
| 126 | }, | 126 | }, |
examples/styles/variables.scss
examples/views/docs/component/table.md
| @@ -36,21 +36,66 @@ export default { | @@ -36,21 +36,66 @@ export default { | ||
| 36 | 36 | ||
| 37 | ::: | 37 | ::: |
| 38 | 38 | ||
| 39 | -## 可编辑表格 | 39 | +## 配置项 |
| 40 | + | ||
| 41 | +可以通过配置项列表快速生成表格列 | ||
| 42 | + | ||
| 43 | +::: snippet 设置`columns`配置表格列,插槽`header-列字段名`可自定义表头的内容,插槽`cell-列字段名`可自定义列单元格的内容。 | ||
| 44 | + | ||
| 45 | +```html | ||
| 46 | +<template> | ||
| 47 | + <z-table :data="tableData" border size="small" :columns="columns"> | ||
| 48 | + <template #header-age>年龄 <i class="el-icon-question"></i></template> | ||
| 49 | + <template #cell-gender="{ value }"> | ||
| 50 | + <el-tag size="mini">{{ value }}</el-tag> | ||
| 51 | + </template> | ||
| 52 | + </z-table> | ||
| 53 | +</template> | ||
| 54 | + | ||
| 55 | +<script> | ||
| 56 | +export default { | ||
| 57 | + data() { | ||
| 58 | + return { | ||
| 59 | + tableData: [ | ||
| 60 | + { name: '张三', age: '31', gender: '男' }, | ||
| 61 | + { name: '李四', age: '27', gender: '女' }, | ||
| 62 | + { name: '王五', age: '16', gender: '男' }, | ||
| 63 | + ], | ||
| 64 | + columns: [ | ||
| 65 | + { prop: 'name', label: '姓名' }, | ||
| 66 | + { prop: 'age', label: '年龄' }, | ||
| 67 | + { prop: 'gender', label: '性别' }, | ||
| 68 | + ] | ||
| 69 | + }; | ||
| 70 | + }, | ||
| 71 | +} | ||
| 72 | +</script> | ||
| 73 | +``` | ||
| 74 | + | ||
| 75 | +::: | ||
| 76 | + | ||
| 77 | +## 追加列 | ||
| 40 | 78 | ||
| 41 | -一般用于表格的静态数据编辑 | 79 | +使用配置项时,**新增的列**则默认追加在**配置项列**之后,使用`left`插槽可在表格的最左侧插入列,顺序在**配置项列**之前 |
| 42 | 80 | ||
| 43 | -::: snippet 设置type为`editable`开启可编辑模式 | 81 | +::: snippet 设置`columns`配置表格列,插槽`header-列字段名`可自定义表头的内容,插槽`cell-列字段名`可自定义列单元格的内容。 |
| 44 | 82 | ||
| 45 | ```html | 83 | ```html |
| 46 | <template> | 84 | <template> |
| 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> | 85 | + <z-table :data="tableData" border size="small" :columns="columns"> |
| 86 | + <template #left> | ||
| 87 | + <el-table-column type="selection" width="40"></el-table-column> | ||
| 88 | + <el-table-column label="左侧的列"> | ||
| 89 | + <template #default="{ $index }"> | ||
| 90 | + 内容 {{ $index }} | ||
| 91 | + </template> | ||
| 92 | + </el-table-column> | ||
| 53 | </template> | 93 | </template> |
| 94 | + <el-table-column label="新增的列" width="80"> | ||
| 95 | + <template #default> | ||
| 96 | + <el-button type="text">编辑</el-button> | ||
| 97 | + </template> | ||
| 98 | + </el-table-column> | ||
| 54 | </z-table> | 99 | </z-table> |
| 55 | </template> | 100 | </template> |
| 56 | 101 | ||
| @@ -59,18 +104,79 @@ export default { | @@ -59,18 +104,79 @@ export default { | ||
| 59 | data() { | 104 | data() { |
| 60 | return { | 105 | return { |
| 61 | tableData: [ | 106 | tableData: [ |
| 107 | + { name: '张三', age: '31', gender: '男' }, | ||
| 108 | + { name: '李四', age: '27', gender: '女' }, | ||
| 109 | + { name: '王五', age: '16', gender: '男' }, | ||
| 110 | + ], | ||
| 111 | + columns: [ | ||
| 112 | + { prop: 'name', label: '姓名' }, | ||
| 113 | + { prop: 'age', label: '年龄' }, | ||
| 114 | + { prop: 'gender', label: '性别' }, | ||
| 115 | + ] | ||
| 116 | + }; | ||
| 117 | + }, | ||
| 118 | +} | ||
| 119 | +</script> | ||
| 120 | +``` | ||
| 121 | + | ||
| 122 | +::: | ||
| 123 | + | ||
| 124 | +## 可编辑表格 | ||
| 125 | + | ||
| 126 | +一般用于表格的静态数据编辑,设置`editable`开启可编辑模式,设置`clickable`开启双击编辑 | ||
| 127 | + | ||
| 128 | +::: snippet 编辑功能只支持通过`columns`配置的列,`editable`设置该列是否可编辑,默认开启;插槽`editor-列字段名`可自定义列单元格的编辑器,通过解构作用域插槽获取的`value`和`onInput`改变表格的绑定值,不支持直接写`v-model`。 | ||
| 129 | + | ||
| 130 | +```html | ||
| 131 | +<template> | ||
| 132 | + <div> | ||
| 133 | + <z-form span="6"> | ||
| 134 | + <z-form-item>编辑模式:<el-switch v-model="editable"></el-switch></z-form-item> | ||
| 135 | + <z-form-item>双击编辑:<el-switch v-model="clickable"></el-switch></z-form-item> | ||
| 136 | + </z-form> | ||
| 137 | + <z-table v-model="tableData" :editable="editable" :columns="columns" border :clickable="clickable" @cell-edit-confirm="onCellEditConfirm"> | ||
| 138 | + <template #editor-gender="{ value, onInput, index }"> | ||
| 139 | + <el-radio-group size="mini" :value="value" @input="onInput"> | ||
| 140 | + <el-radio-button label="男">男</el-radio-button> | ||
| 141 | + <el-radio-button label="女">女</el-radio-button> | ||
| 142 | + </el-radio-group> | ||
| 143 | + </template> | ||
| 144 | + <el-table-column label="操作" width="80"> | ||
| 145 | + <template #default="{ $index }"> | ||
| 146 | + <el-button type="text" @click="deleteRow($index)">删除</el-button> | ||
| 147 | + </template> | ||
| 148 | + </el-table-column> | ||
| 149 | + </z-table> | ||
| 150 | + </div> | ||
| 151 | +</template> | ||
| 152 | + | ||
| 153 | +<script> | ||
| 154 | +export default { | ||
| 155 | + data() { | ||
| 156 | + return { | ||
| 157 | + editable: true, | ||
| 158 | + clickable: true, | ||
| 159 | + tableData: [ | ||
| 62 | { name: '张三', age: 31, gender: '男', remark: '' }, | 160 | { name: '张三', age: 31, gender: '男', remark: '' }, |
| 63 | { name: '李四', age: 27, gender: '女', remark: '' }, | 161 | { name: '李四', age: 27, gender: '女', remark: '' }, |
| 64 | { name: '王五', age: 16, gender: '男', remark: '' }, | 162 | { name: '王五', age: 16, gender: '男', remark: '' }, |
| 65 | ], | 163 | ], |
| 66 | columns: [ | 164 | columns: [ |
| 67 | { prop: 'name', label: '姓名', editable: false }, | 165 | { prop: 'name', label: '姓名', editable: false }, |
| 68 | - { type: 'el-input-number', prop: 'age', label: '年龄' }, | 166 | + { component: 'el-input-number', prop: 'age', label: '年龄' }, |
| 69 | { prop: 'gender', label: '性别' }, | 167 | { prop: 'gender', label: '性别' }, |
| 70 | { prop: 'remark', label: '备注' }, | 168 | { prop: 'remark', label: '备注' }, |
| 71 | ] | 169 | ] |
| 72 | }; | 170 | }; |
| 73 | }, | 171 | }, |
| 172 | + methods: { | ||
| 173 | + deleteRow(index) { | ||
| 174 | + this.tableData.splice(index, 1); | ||
| 175 | + }, | ||
| 176 | + onCellEditConfirm(data) { | ||
| 177 | + console.log(data); | ||
| 178 | + } | ||
| 179 | + } | ||
| 74 | } | 180 | } |
| 75 | </script> | 181 | </script> |
| 76 | ``` | 182 | ``` |
examples/views/docs/develop/mixin.md
| @@ -1,62 +0,0 @@ | @@ -1,62 +0,0 @@ | ||
| 1 | -# Mixin 混入 | ||
| 2 | - | ||
| 3 | -根据JSON Scheme配置自动生成一个筛选条件表单 | ||
| 4 | - | ||
| 5 | -## 基础用法 | ||
| 6 | - | ||
| 7 | -配置`list`属性设置JSON Scheme配置列表 | ||
| 8 | - | ||
| 9 | -::: snippet 通过`list`配置项目 | ||
| 10 | - | ||
| 11 | -```html | ||
| 12 | -<template> | ||
| 13 | - <div> | ||
| 14 | - <div class="page-search"> | ||
| 15 | - <el-form :model="searchModel" label-width="80px" size="small"> | ||
| 16 | - <el-row> | ||
| 17 | - <el-col :span="6"> | ||
| 18 | - <el-form-item label="姓名"> | ||
| 19 | - <el-input v-model.trim="searchModel.name"></el-input> | ||
| 20 | - </el-form-item> | ||
| 21 | - </el-col> | ||
| 22 | - <el-col :span="6"> | ||
| 23 | - <el-form-item label="手机号"> | ||
| 24 | - <el-input v-model.trim="searchModel.mobile"></el-input> | ||
| 25 | - </el-form-item> | ||
| 26 | - </el-col> | ||
| 27 | - </el-row> | ||
| 28 | - </el-form> | ||
| 29 | - </div> | ||
| 30 | - <div class="page-action"> | ||
| 31 | - <el-button type="primary" size="small">新增</el-button> | ||
| 32 | - </div> | ||
| 33 | - <el-table class="page-table" v-loading="loading" size="small" :data="tableData" border highlight-current-row> | ||
| 34 | - <el-table-column label="姓名" prop="name" min-width="100" show-overflow-tooltip></el-table-column> | ||
| 35 | - <el-table-column label="手机号" prop="mobile" min-width="120" show-overflow-tooltip></el-table-column> | ||
| 36 | - </el-table> | ||
| 37 | - <el-pagination class="page-pagination" v-bind="paginationProps" v-on="paginationEvent"></el-pagination> | ||
| 38 | - </div> | ||
| 39 | -</template> | ||
| 40 | - | ||
| 41 | -<script> | ||
| 42 | -// import MIX_PAGE from '@/mixins/page'; | ||
| 43 | - | ||
| 44 | -export default { | ||
| 45 | - // mixins: [MIX_PAGE], | ||
| 46 | - mixins: [window.MIX_PAGE], | ||
| 47 | - data() { | ||
| 48 | - return { | ||
| 49 | - searchModel: { | ||
| 50 | - name: '', | ||
| 51 | - mobile: '', | ||
| 52 | - }, | ||
| 53 | - }; | ||
| 54 | - }, | ||
| 55 | - methods: { | ||
| 56 | - }, | ||
| 57 | -}; | ||
| 58 | -</script> | ||
| 59 | - | ||
| 60 | -``` | ||
| 61 | - | ||
| 62 | -::: | ||
| 63 | \ No newline at end of file | 0 | \ No newline at end of file |
| @@ -0,0 +1,331 @@ | @@ -0,0 +1,331 @@ | ||
| 1 | +# Mixin Page 标准页 | ||
| 2 | + | ||
| 3 | +根据JSON Scheme配置自动生成一个筛选条件表单 | ||
| 4 | + | ||
| 5 | +## 基础用法 | ||
| 6 | + | ||
| 7 | +`MIX_PAGE`混入配置项,会默认提供一套分页查询的业务逻辑。 | ||
| 8 | + | ||
| 9 | +::: snippet 预置了许多业务逻辑,避免重复维护相同的业务逻辑 | ||
| 10 | + | ||
| 11 | +```html | ||
| 12 | +<template> | ||
| 13 | + <div> | ||
| 14 | + <div class="page-search"> | ||
| 15 | + <el-form :model="searchModel" label-width="80px" size="small"> | ||
| 16 | + <el-row> | ||
| 17 | + <el-col :span="6"> | ||
| 18 | + <el-form-item label="姓名"> | ||
| 19 | + <el-input v-model.trim="searchModel.name"></el-input> | ||
| 20 | + </el-form-item> | ||
| 21 | + </el-col> | ||
| 22 | + <el-col :span="18" style="text-align: right;"> | ||
| 23 | + <el-form-item> | ||
| 24 | + <el-button-group> | ||
| 25 | + <el-button :loading="loading" type="primary" @click="onSearch">查询</el-button> | ||
| 26 | + <el-button @click="onReset">重置</el-button> | ||
| 27 | + </el-button-group> | ||
| 28 | + </el-form-item> | ||
| 29 | + </el-col> | ||
| 30 | + </el-row> | ||
| 31 | + </el-form> | ||
| 32 | + </div> | ||
| 33 | + <div class="page-action"> | ||
| 34 | + <el-button type="primary" size="small">新增</el-button> | ||
| 35 | + </div> | ||
| 36 | + <el-table class="page-table" v-loading="loading" v-bind="tableProps" :data="tableData"> | ||
| 37 | + <el-table-column label="姓名" prop="name" min-width="100" show-overflow-tooltip></el-table-column> | ||
| 38 | + <el-table-column label="年龄" prop="age" min-width="120" show-overflow-tooltip></el-table-column> | ||
| 39 | + </el-table> | ||
| 40 | + <el-pagination class="page-pagination" v-bind="paginationProps" v-on="paginationEvent"></el-pagination> | ||
| 41 | + </div> | ||
| 42 | +</template> | ||
| 43 | + | ||
| 44 | +<script> | ||
| 45 | +// import MIX_PAGE from '@/mixins/page'; 注:使用时解除此注释 | ||
| 46 | + | ||
| 47 | +export default { | ||
| 48 | + mixins: [MIX_PAGE], | ||
| 49 | + data() { | ||
| 50 | + return { | ||
| 51 | + searchModel: { | ||
| 52 | + name: '', | ||
| 53 | + }, | ||
| 54 | + }; | ||
| 55 | + }, | ||
| 56 | + methods: { | ||
| 57 | + searchAPI(params) { | ||
| 58 | + return new Promise(resolve => { | ||
| 59 | + setTimeout(() => { | ||
| 60 | + const source = [ | ||
| 61 | + { id: '0', name: '李饼', age: 32 }, | ||
| 62 | + { id: '1', name: '陈拾', age: 20 }, | ||
| 63 | + { id: '3', name: '王七', age: 26 }, | ||
| 64 | + { id: '4', name: '崔倍', age: 27 }, | ||
| 65 | + { id: '5', name: '孙豹', age: 38 }, | ||
| 66 | + { id: '6', name: '庞柏', age: 42 }, | ||
| 67 | + { id: '7', name: '蔡疏', age: 60 }, | ||
| 68 | + { id: '8', name: '卢纳', age: 55 }, | ||
| 69 | + ]; | ||
| 70 | + const list = source.filter(item => `${item.name}`.includes(params.name)); | ||
| 71 | + resolve({ | ||
| 72 | + result: list, | ||
| 73 | + totalCount: list.length | ||
| 74 | + }); | ||
| 75 | + }, 1500); | ||
| 76 | + }); | ||
| 77 | + }, | ||
| 78 | + }, | ||
| 79 | +}; | ||
| 80 | +</script> | ||
| 81 | + | ||
| 82 | +``` | ||
| 83 | + | ||
| 84 | +::: | ||
| 85 | + | ||
| 86 | +## 推荐用法 | ||
| 87 | + | ||
| 88 | +与`z-form`、`z-table`等组件配合,可以最大限度的减少代码量,开发者只需要重点关心与业务相关的数据渲染 | ||
| 89 | + | ||
| 90 | +::: snippet `MIX_PAGE`混入配置项,会默认提供一套分页查询的业务逻辑。 | ||
| 91 | + | ||
| 92 | +```html | ||
| 93 | +<template> | ||
| 94 | + <div> | ||
| 95 | + <div class="page-search"> | ||
| 96 | + <z-form :model="searchModel" label-width="80px" size="small" span="6"> | ||
| 97 | + <z-form-item label="姓名" prop="name"> | ||
| 98 | + <el-input v-model="searchModel.name"></el-input> | ||
| 99 | + </z-form-item> | ||
| 100 | + <z-form-item span="18" style="text-align: right"> | ||
| 101 | + <el-button-group> | ||
| 102 | + <el-button :loading="loading" type="primary" @click="onSearch">查询</el-button> | ||
| 103 | + <el-button @click="onReset">重置</el-button> | ||
| 104 | + </el-button-group> | ||
| 105 | + </z-form-item> | ||
| 106 | + </z-form> | ||
| 107 | + </div> | ||
| 108 | + <div class="page-action"> | ||
| 109 | + <el-button type="primary" size="small">新增</el-button> | ||
| 110 | + </div> | ||
| 111 | + <z-table class="page-table" v-loading="loading" v-bind="tableProps"> | ||
| 112 | + <el-table-column prop="name" label="姓名"></el-table-column> | ||
| 113 | + <el-table-column prop="age" label="年龄"></el-table-column> | ||
| 114 | + </z-table> | ||
| 115 | + <el-pagination class="page-pagination" v-bind="paginationProps" v-on="paginationEvent"></el-pagination> | ||
| 116 | + </div> | ||
| 117 | +</template> | ||
| 118 | + | ||
| 119 | +<script> | ||
| 120 | +// import MIX_PAGE from '@/mixins/page'; 注:使用时解除此注释 | ||
| 121 | + | ||
| 122 | +export default { | ||
| 123 | + mixins: [MIX_PAGE], | ||
| 124 | + data() { | ||
| 125 | + return { | ||
| 126 | + searchModel: { | ||
| 127 | + name: '', | ||
| 128 | + }, | ||
| 129 | + }; | ||
| 130 | + }, | ||
| 131 | + methods: { | ||
| 132 | + searchAPI(params) { | ||
| 133 | + return new Promise(resolve => { | ||
| 134 | + setTimeout(() => { | ||
| 135 | + const source = [ | ||
| 136 | + { id: '0', name: '李饼', age: 32 }, | ||
| 137 | + { id: '1', name: '陈拾', age: 20 }, | ||
| 138 | + { id: '3', name: '王七', age: 26 }, | ||
| 139 | + { id: '4', name: '崔倍', age: 27 }, | ||
| 140 | + { id: '5', name: '孙豹', age: 38 }, | ||
| 141 | + { id: '6', name: '庞柏', age: 42 }, | ||
| 142 | + { id: '7', name: '蔡疏', age: 60 }, | ||
| 143 | + { id: '8', name: '卢纳', age: 55 }, | ||
| 144 | + ]; | ||
| 145 | + const list = source.filter(item => `${item.name}`.includes(params.name)); | ||
| 146 | + resolve({ | ||
| 147 | + result: list, | ||
| 148 | + totalCount: list.length | ||
| 149 | + }); | ||
| 150 | + }, 1500); | ||
| 151 | + }); | ||
| 152 | + }, | ||
| 153 | + }, | ||
| 154 | +}; | ||
| 155 | +</script> | ||
| 156 | + | ||
| 157 | +``` | ||
| 158 | + | ||
| 159 | +::: | ||
| 160 | + | ||
| 161 | +## 内置方法 | ||
| 162 | + | ||
| 163 | +本混入配置中,内置了`originData`对象和`getOriginData`方法。 | ||
| 164 | + | ||
| 165 | +::: snippet `originData`表示当前页面的初始data值,`getOriginData`方法可获得一个新的初始值对象 | ||
| 166 | + | ||
| 167 | +```html | ||
| 168 | +<template> | ||
| 169 | + <div> | ||
| 170 | + <div>model初始值:{{ originData.model }}</div> | ||
| 171 | + <el-input v-model="model.name" size="mini" style="width: 200px; margin: 10px 0"></el-input> | ||
| 172 | + <el-button type="primary" size="mini" @click="handleReset">重置</el-button> | ||
| 173 | + <div>model当前值:{{ model }}</div> | ||
| 174 | + </div> | ||
| 175 | +</template> | ||
| 176 | + | ||
| 177 | +<script> | ||
| 178 | +export default { | ||
| 179 | + mixins: [MIX_PAGE], | ||
| 180 | + data() { | ||
| 181 | + return { | ||
| 182 | + model: { | ||
| 183 | + name: '张三', | ||
| 184 | + }, | ||
| 185 | + }; | ||
| 186 | + }, | ||
| 187 | + methods: { | ||
| 188 | + handleReset() { | ||
| 189 | + // 注意:切记不可写成 this.model = this.originData.model; 否则会导致originData被改变! | ||
| 190 | + this.model = this.getOriginData().model; | ||
| 191 | + } | ||
| 192 | + }, | ||
| 193 | +}; | ||
| 194 | +</script> | ||
| 195 | +``` | ||
| 196 | + | ||
| 197 | +::: | ||
| 198 | + | ||
| 199 | +## 源文件 | ||
| 200 | + | ||
| 201 | +```js | ||
| 202 | +import MIX_ORIGIN from '@/mixins/origin'; // 初始值逻辑混入 | ||
| 203 | + | ||
| 204 | +export default { | ||
| 205 | + mixins: [MIX_ORIGIN], | ||
| 206 | + data() { | ||
| 207 | + return { | ||
| 208 | + auto: true, // 页面加载时自动查询 | ||
| 209 | + tableData: [], // 表格数据 | ||
| 210 | + loading: false, // 加载状态 | ||
| 211 | + total: 0, // 数据总量 | ||
| 212 | + currentPage: 1, // 当前页码 | ||
| 213 | + pageSize: 10, // 分页大小 | ||
| 214 | + pageSizes: [10, 20, 50, 100], // 分页大小选项 | ||
| 215 | + layout: 'total, sizes, prev, pager, next, jumper', // 分页器默认设置 | ||
| 216 | + searchModel: {}, // 搜索表单绑定值 | ||
| 217 | + form: {}, // 常规表单绑定值 | ||
| 218 | + submitting: false, // 提交状态 | ||
| 219 | + selection: [], // 表格选中项 | ||
| 220 | + collapsed: false, // 展开状态 | ||
| 221 | + }; | ||
| 222 | + }, | ||
| 223 | + computed: { | ||
| 224 | + // 搜索栏折叠按钮文本 | ||
| 225 | + toggleText() { | ||
| 226 | + return this.collapsed ? '收起' : '展开'; | ||
| 227 | + }, | ||
| 228 | + // 表格属性 | ||
| 229 | + tableProps() { | ||
| 230 | + return { | ||
| 231 | + size: 'mini', | ||
| 232 | + rowKey: 'id', | ||
| 233 | + border: true, | ||
| 234 | + highlightCurrentRow: true, | ||
| 235 | + data: this.tableData, | ||
| 236 | + }; | ||
| 237 | + }, | ||
| 238 | + // 表格事件 | ||
| 239 | + tableEvent() { | ||
| 240 | + return { | ||
| 241 | + 'selection-change': this.onSelectionChange, | ||
| 242 | + }; | ||
| 243 | + }, | ||
| 244 | + // 分页参数 | ||
| 245 | + pageParams() { | ||
| 246 | + return { | ||
| 247 | + currentPage: this.currentPage, | ||
| 248 | + pageSize: this.pageSize, | ||
| 249 | + }; | ||
| 250 | + }, | ||
| 251 | + // 分页器属性 | ||
| 252 | + paginationProps() { | ||
| 253 | + return { | ||
| 254 | + 'current-page': this.currentPage, | ||
| 255 | + 'page-sizes': this.pageSizes, | ||
| 256 | + 'page-size': this.pageSize, | ||
| 257 | + layout: this.layout, | ||
| 258 | + total: this.total, | ||
| 259 | + }; | ||
| 260 | + }, | ||
| 261 | + // 分页器事件 | ||
| 262 | + paginationEvent() { | ||
| 263 | + return { | ||
| 264 | + 'size-change': this.onPageSizeChange, | ||
| 265 | + 'current-change': this.onCurrentPageChange, | ||
| 266 | + }; | ||
| 267 | + }, | ||
| 268 | + }, | ||
| 269 | + created() { | ||
| 270 | + if (this.auto) { | ||
| 271 | + this.search(); | ||
| 272 | + } | ||
| 273 | + }, | ||
| 274 | + methods: { | ||
| 275 | + // 空Promise | ||
| 276 | + emptyPromise() { | ||
| 277 | + return new Promise(resolve => resolve()); | ||
| 278 | + }, | ||
| 279 | + // 重置查询 | ||
| 280 | + onSearch() { | ||
| 281 | + this.currentPage = 1; | ||
| 282 | + this.loadData(); | ||
| 283 | + }, | ||
| 284 | + // 切换展开状态 | ||
| 285 | + toggle() { | ||
| 286 | + this.collapsed = !this.collapsed; | ||
| 287 | + }, | ||
| 288 | + // 查询数据 | ||
| 289 | + search() { | ||
| 290 | + this.loadData(); | ||
| 291 | + }, | ||
| 292 | + // 加载数据 | ||
| 293 | + async loadData() { | ||
| 294 | + this.loading = true; | ||
| 295 | + const params = { | ||
| 296 | + ...this.searchModel, | ||
| 297 | + ...this.pageParams, | ||
| 298 | + }; | ||
| 299 | + const searchAPI = this.searchAPI || this.emptyPromise; | ||
| 300 | + await searchAPI(params) | ||
| 301 | + .then(response => { | ||
| 302 | + const { result = [], totalCount = 0 } = response || {}; | ||
| 303 | + this.tableData = result || []; | ||
| 304 | + this.total = totalCount || 0; | ||
| 305 | + }) | ||
| 306 | + .finally(() => { | ||
| 307 | + this.loading = false; | ||
| 308 | + }); | ||
| 309 | + }, | ||
| 310 | + // 重置搜索表单 | ||
| 311 | + onReset() { | ||
| 312 | + this.searchModel = this.cloneDeep(this.originData).searchModel; | ||
| 313 | + }, | ||
| 314 | + // 多选 | ||
| 315 | + onSelectionChange(selection) { | ||
| 316 | + this.selection = selection; | ||
| 317 | + }, | ||
| 318 | + // 切换当前页码 | ||
| 319 | + onCurrentPageChange(value) { | ||
| 320 | + this.currentPage = value; | ||
| 321 | + this.$nextTick(this.loadData); | ||
| 322 | + }, | ||
| 323 | + // 切换最大页码 | ||
| 324 | + onPageSizeChange(value) { | ||
| 325 | + this.currentPage = 1; | ||
| 326 | + this.pageSize = value; | ||
| 327 | + this.$nextTick(this.loadData); | ||
| 328 | + }, | ||
| 329 | + }, | ||
| 330 | +}; | ||
| 331 | +``` | ||
| 0 | \ No newline at end of file | 332 | \ No newline at end of file |
packages/table/editable.vue
| @@ -28,6 +28,7 @@ | @@ -28,6 +28,7 @@ | ||
| 28 | 28 | ||
| 29 | <template> | 29 | <template> |
| 30 | <el-table :data="tableData | tableDataFilter" :size="tableSize" v-bind="_props" @header-click="onHeaderClick" @cell-click="onCellClick" @cell-dblclick="onCellDblclick"> | 30 | <el-table :data="tableData | tableDataFilter" :size="tableSize" v-bind="_props" @header-click="onHeaderClick" @cell-click="onCellClick" @cell-dblclick="onCellDblclick"> |
| 31 | + <slot name="left"></slot> | ||
| 31 | <template v-for="(item, index) in columns"> | 32 | <template v-for="(item, index) in columns"> |
| 32 | <el-table-column v-bind="item" :key="index"> | 33 | <el-table-column v-bind="item" :key="index"> |
| 33 | <slot :name="`header-${item.prop}`" slot="header"></slot> | 34 | <slot :name="`header-${item.prop}`" slot="header"></slot> |
| @@ -35,11 +36,11 @@ | @@ -35,11 +36,11 @@ | ||
| 35 | <cell-editor | 36 | <cell-editor |
| 36 | :disabled="disabled || item.editable === false" | 37 | :disabled="disabled || item.editable === false" |
| 37 | :editable="item.editable !== false && (row.$editable || (tableEditCell.index === row.$index && tableEditCell.prop === item.prop))" | 38 | :editable="item.editable !== false && (row.$editable || (tableEditCell.index === row.$index && tableEditCell.prop === item.prop))" |
| 38 | - :type="item.type" | 39 | + :component="item.component" |
| 39 | :value="row[column.property]" | 40 | :value="row[column.property]" |
| 40 | @input="onCellInput" | 41 | @input="onCellInput" |
| 41 | @edit-click="setEditCell(row, column)" | 42 | @edit-click="setEditCell(row, column)" |
| 42 | - @edit-confirm="cancelEditCell" | 43 | + @edit-confirm="onEditConfirm" |
| 43 | > | 44 | > |
| 44 | <template v-if="$scopedSlots[`editor-${item.prop}`]"> | 45 | <template v-if="$scopedSlots[`editor-${item.prop}`]"> |
| 45 | <slot :name="`editor-${item.prop}`" :value="row[column.property]" :onInput="onCellInput"></slot> | 46 | <slot :name="`editor-${item.prop}`" :value="row[column.property]" :onInput="onCellInput"></slot> |
| @@ -48,6 +49,8 @@ | @@ -48,6 +49,8 @@ | ||
| 48 | </template> | 49 | </template> |
| 49 | </el-table-column> | 50 | </el-table-column> |
| 50 | </template> | 51 | </template> |
| 52 | + <slot></slot> | ||
| 53 | + <slot name="append"></slot> | ||
| 51 | </el-table> | 54 | </el-table> |
| 52 | </template> | 55 | </template> |
| 53 | 56 | ||
| @@ -63,13 +66,13 @@ export default { | @@ -63,13 +66,13 @@ export default { | ||
| 63 | cellEditor: { | 66 | cellEditor: { |
| 64 | props: { | 67 | props: { |
| 65 | value: [String, Number, Array, Object], | 68 | value: [String, Number, Array, Object], |
| 66 | - type: { type: String, default: 'el-input' }, | 69 | + component: { type: String, default: 'el-input' }, |
| 67 | editable: Boolean, | 70 | editable: Boolean, |
| 68 | disabled: Boolean, | 71 | disabled: Boolean, |
| 69 | }, | 72 | }, |
| 70 | watch: { | 73 | watch: { |
| 71 | editable(val) { | 74 | editable(val) { |
| 72 | - if (val && this.type === 'el-input') { | 75 | + if (val && this.component === 'el-input') { |
| 73 | this.$nextTick(() => { | 76 | this.$nextTick(() => { |
| 74 | this.$children[0] && this.$children[0].focus && this.$children[0].focus(); | 77 | this.$children[0] && this.$children[0].focus && this.$children[0].focus(); |
| 75 | }); | 78 | }); |
| @@ -79,7 +82,7 @@ export default { | @@ -79,7 +82,7 @@ export default { | ||
| 79 | render(h) { | 82 | render(h) { |
| 80 | if (this.editable) { | 83 | if (this.editable) { |
| 81 | let editorRender = [ | 84 | let editorRender = [ |
| 82 | - h(this.type, { | 85 | + h(this.component, { |
| 83 | props: { value: this.value, size: 'mini' }, | 86 | props: { value: this.value, size: 'mini' }, |
| 84 | on: { | 87 | on: { |
| 85 | input: value => { | 88 | input: value => { |
| @@ -92,7 +95,7 @@ export default { | @@ -92,7 +95,7 @@ export default { | ||
| 92 | editorRender = [this.$scopedSlots.default()]; | 95 | editorRender = [this.$scopedSlots.default()]; |
| 93 | } | 96 | } |
| 94 | if (!this.disabled) { | 97 | if (!this.disabled) { |
| 95 | - const handlerItems = [h('i', { attrs: { title: '确定', class: 'el-icon-check' }, on: { click: () => this.$emit('edit-confirm') } })]; | 98 | + const handlerItems = [h('i', { attrs: { title: '确定', class: 'el-icon-check' }, on: { click: () => this.$emit('edit-confirm', this.value) } })]; |
| 96 | // handlerItems.push(h('i', { attrs: { title: '取消', class: 'el-icon-close' }, on: { click: () => this.$emit('edit-confirm') } })); | 99 | // handlerItems.push(h('i', { attrs: { title: '取消', class: 'el-icon-close' }, on: { click: () => this.$emit('edit-confirm') } })); |
| 97 | const handler = h('span', handlerItems); | 100 | const handler = h('span', handlerItems); |
| 98 | editorRender.push(handler); | 101 | editorRender.push(handler); |
| @@ -163,6 +166,10 @@ export default { | @@ -163,6 +166,10 @@ export default { | ||
| 163 | setEditCell(row, column) { | 166 | setEditCell(row, column) { |
| 164 | this.tableEditCell = { index: row.$index, prop: column.property }; | 167 | this.tableEditCell = { index: row.$index, prop: column.property }; |
| 165 | }, | 168 | }, |
| 169 | + onEditConfirm(value) { | ||
| 170 | + this.$emit('cell-edit-confirm', { ...this.tableEditCell, value }); | ||
| 171 | + this.cancelEditCell(); | ||
| 172 | + }, | ||
| 166 | cancelEditCell() { | 173 | cancelEditCell() { |
| 167 | this.tableEditCell = {}; | 174 | this.tableEditCell = {}; |
| 168 | }, | 175 | }, |
packages/table/index.js
| @@ -3,10 +3,6 @@ import tableProps from './props'; | @@ -3,10 +3,6 @@ import tableProps from './props'; | ||
| 3 | export default { | 3 | export default { |
| 4 | name: 'Table', | 4 | name: 'Table', |
| 5 | props: { | 5 | props: { |
| 6 | - type: { | ||
| 7 | - type: String, | ||
| 8 | - default: 'normal', | ||
| 9 | - }, | ||
| 10 | value: { | 6 | value: { |
| 11 | type: Array, | 7 | type: Array, |
| 12 | default() { | 8 | default() { |
| @@ -19,12 +15,14 @@ export default { | @@ -19,12 +15,14 @@ export default { | ||
| 19 | return []; | 15 | return []; |
| 20 | }, | 16 | }, |
| 21 | }, | 17 | }, |
| 18 | + editable: Boolean, | ||
| 22 | clickable: Boolean, | 19 | clickable: Boolean, |
| 23 | disabled: Boolean, | 20 | disabled: Boolean, |
| 24 | ...tableProps, | 21 | ...tableProps, |
| 25 | }, | 22 | }, |
| 26 | render(h) { | 23 | render(h) { |
| 27 | const scopedSlots = this.$scopedSlots; | 24 | const scopedSlots = this.$scopedSlots; |
| 28 | - return h(`z-table-${this.type}`, { props: { ...this._props }, scopedSlots }); | 25 | + const listeners = this.$listeners; |
| 26 | + return h(`z-table-${this.editable ? 'editable' : 'normal'}`, { props: { ...this._props }, scopedSlots, on: listeners }); | ||
| 29 | }, | 27 | }, |
| 30 | }; | 28 | }; |
packages/table/normal.vue
| 1 | <template> | 1 | <template> |
| 2 | - <el-table :size="tableSize" v-bind="_props"> | 2 | + <el-table :data="tableData" :size="tableSize" v-bind="_props"> |
| 3 | + <slot name="left"></slot> | ||
| 4 | + <template v-for="(item, index) in columns"> | ||
| 5 | + <el-table-column v-bind="item" :key="index"> | ||
| 6 | + <slot :name="`header-${item.prop}`" slot="header"></slot> | ||
| 7 | + <template v-if="$scopedSlots[`cell-${item.prop}`]" #default="{ row, column, $index }"> | ||
| 8 | + <slot :name="`cell-${item.prop}`" :value="row[column.property]" :row="row" :index="$index"></slot> | ||
| 9 | + </template> | ||
| 10 | + </el-table-column> | ||
| 11 | + </template> | ||
| 3 | <slot></slot> | 12 | <slot></slot> |
| 4 | <slot name="append"></slot> | 13 | <slot name="append"></slot> |
| 5 | </el-table> | 14 | </el-table> |
| @@ -19,8 +28,30 @@ export default { | @@ -19,8 +28,30 @@ export default { | ||
| 19 | }, | 28 | }, |
| 20 | }, | 29 | }, |
| 21 | props: { | 30 | props: { |
| 31 | + value: { | ||
| 32 | + type: Array, | ||
| 33 | + default() { | ||
| 34 | + return []; | ||
| 35 | + }, | ||
| 36 | + }, | ||
| 37 | + columns: { | ||
| 38 | + type: Array, | ||
| 39 | + default() { | ||
| 40 | + return []; | ||
| 41 | + }, | ||
| 42 | + }, | ||
| 22 | ...tableProps, | 43 | ...tableProps, |
| 23 | }, | 44 | }, |
| 45 | + data() { | ||
| 46 | + return { | ||
| 47 | + tableData: this.value.length > 0 ? this.value : this.data, | ||
| 48 | + }; | ||
| 49 | + }, | ||
| 50 | + watch: { | ||
| 51 | + value(val) { | ||
| 52 | + this.tableData = val || []; | ||
| 53 | + }, | ||
| 54 | + }, | ||
| 24 | computed: { | 55 | computed: { |
| 25 | _elFormItemSize() { | 56 | _elFormItemSize() { |
| 26 | return (this.elFormItem || {}).elFormItemSize; | 57 | return (this.elFormItem || {}).elFormItemSize; |