当前位置:   article > 正文

Vue + Element-ui实现后台管理系统(5)—封装一个Form表单组件和Table表格组件

vue+elmentui 搭建后台管理系统

封装一个Form表单组件和Table组件

有关后台管理系统之前写过四遍博客,看这篇之前最好先看下这四篇博客。另外这里只展示关键部分代码,项目代码放在github上: mall-manage-system

1、Vue + Element-ui实现后台管理系统(1) — 总述

2、Vue + Element-ui实现后台管理系统(2) — 项目搭建 + ⾸⻚布局实现

3、Vue + Element-ui实现后台管理系统(3) — 面包屑 + Tag标签切换功能

4、Vue + Element-ui实现后台管理系统(4)—封装一个ECharts组件的一点思路

这篇主要讲解实现图表的功能:

整体效果

图片效果

一、封装一个Form表单组件

1、封装思路

我们需要看下一个基础form组件,需要哪些数据。我们看下官网一个示例 Form 表单

  1. <template>
  2. <el-form ref="form" :model="form" label-width="80px">
  3. <el-form-item label="姓名" >
  4. <el-input v-model="form.name" style="width: 195px"></el-input>
  5. </el-form-item>
  6. <el-form-item label="国籍">
  7. <el-select v-model="form.region" placeholder="请选择国籍">
  8. <el-option label="中国" value="china"></el-option>
  9. <el-option label="美国" value="America"></el-option>
  10. </el-select>
  11. </el-form-item>
  12. <el-form-item label="爱好">
  13. <el-checkbox-group v-model="form.type">
  14. <el-checkbox label="画画" name="type" ></el-checkbox>
  15. <el-checkbox label="吹泡泡" name="type"></el-checkbox>
  16. <el-checkbox label="放风筝" name="type"></el-checkbox>
  17. <el-checkbox label="看佩琦" name="type"></el-checkbox>
  18. </el-checkbox-group>
  19. </el-form-item>
  20. <el-form-item>
  21. <el-button type="primary" @click="onSubmit" size="small">立即创建</el-button>
  22. </el-form-item>
  23. </el-form>
  24. </template>
  25. <script>
  26. export default {
  27. data() {
  28. return {
  29. form: {
  30. name: '',
  31. region: '',
  32. type: []
  33. }
  34. }
  35. },
  36. methods: {
  37. onSubmit() {
  38. console.log('提交 -> ' + this.form.name + " " + this.form.region + " " + this.form.type );
  39. }
  40. }
  41. }
  42. </script>

运行结果

从这个简单的示例,至少有两份数据是需要父组件传入到表单组件中的:

1、v-model对应的数据,这份数据是用户选择好后给父组件的,所以是双向绑定的。

2、label 对应的数据,这里是写死的,既然要封装成一个控件那么这份数据也需要父组件传过来。

注意 这里需要注意的一点就是标签的类型是input 还是select是需要外面传来过来的数据告知的。同时如果是select那么还需要把option下面的数据返回。

2、封装Form组件

新建一个CommonForm.vue,作为封装Form的组件

  1. <template>
  2. <!--是否行内表单-->
  3. <el-form :inline="inline" :model="form" ref="form" label-width="100px">
  4. <!--标签显示名称-->
  5. <el-form-item v-for="item in formLabel" :key="item.model" :label="item.label">
  6. <!--根据type来显示是什么标签-->
  7. <el-input v-model="form[item.model]" :placeholder="'请输入' + item.label" v-if="item.type==='input'"></el-input>
  8. <el-select v-model="form[item.model]" placeholder="请选择" v-if="item.type === 'select'">
  9. <!--如果是select或者checkbox 、Radio就还需要选项信息-->
  10. <el-option v-for="item in item.opts" :key="item.value" :label="item.label" :value="item.value"></el-option>
  11. </el-select>
  12. <el-switch v-model="form[item.model]" v-if="item.type === 'switch'"></el-switch>
  13. <el-date-picker v-model="form[item.model]" type="date" placeholder="选择日期" v-if="item.type === 'date'" value-format="yyyy-MM-dd"> </el-date-picker>
  14. </el-form-item>
  15. <!--留一个插槽-->
  16. <el-form-item><slot></slot></el-form-item>
  17. </el-form>
  18. </template>
  19. <script>
  20. export default {
  21. //inline 属性可以让表单域变为行内的表单域
  22. //form 表单数据 formLabel 是标签数据
  23. props: {
  24. inline: Boolean,
  25. form: Object,
  26. formLabel: Array
  27. }
  28. }
  29. </script>

这样一个简单的表单公共组件就完成了。

一、封装一个Table组件

1、封装思路

同样我们需要去看下element有关表格最简单的示例。Table 表格

代码示例

  1. <template>
  2. <el-table
  3. :data="tableData"
  4. style="width: 100%">
  5. <el-table-column
  6. prop="date"
  7. label="日期"
  8. width="180">
  9. </el-table-column>
  10. <el-table-column
  11. prop="name"
  12. label="姓名"
  13. width="180">
  14. </el-table-column>
  15. <el-table-column
  16. prop="address"
  17. label="地址">
  18. </el-table-column>
  19. </el-table>
  20. </template>
  21. <script>
  22. export default {
  23. data() {
  24. return {
  25. tableData: [{
  26. date: '2017-05-04',
  27. name: '小小',
  28. address: '浙江省杭州市千岛湖镇 阳光路'
  29. }, {
  30. date: '1956-05-04',
  31. name: '爷爷',
  32. address: '浙江省杭州市千岛湖镇 清波花园'
  33. }, {
  34. date: '1958-05-04',
  35. name: '奶奶',
  36. address: '浙江省杭州市千岛湖镇 冬瓜乌'
  37. }]
  38. }
  39. }
  40. }
  41. </script>

运行结果

从这个简单的示例,至少也是两份数据是需要父组件传入到表格组件中的:

1、v-model对应的数据,这份数据是用户选择好后给父组件的。

2、label 对应的数据,这里是写死的,既然要封装成一个控件那么这份数据也需要外面传过来。

注意 这里除了上面这两份数据外,还有一份数据在实际开发中也是需要的,那就是分页信息,因为一般table数据都会比较多所以分页还是非常需要的。

2、封装Table组件

新建一个CommonTable.vue,作为封装Table的组件

  1. <template>
  2. <div class="common-table">
  3. <!--stripe 是否为斑马纹 v-loading在请求数据未返回的时间有个加载的图案,提高用户体验-->
  4. <el-table :data="tableData" height="90%" stripe v-loading="config.loading">
  5. <!--第一行为序号 默认写死-->
  6. <el-table-column label="序号" width="85">
  7. <!--slot-scope="scope" 这里取到当前单元格,scope.$index就是索引 默认从0开始这里从1开始-->
  8. <template slot-scope="scope">
  9. <span style="margin-left: 10px">{{ (config.page - 1) * 20 + scope.$index + 1 }}</span>
  10. </template>
  11. </el-table-column>
  12. <!--show-overflow-tooltip 当内容过长被隐藏时显示 tooltip-->
  13. <el-table-column show-overflow-tooltip v-for="item in tableLabel" :key="item.prop" :label="item.label" :width="item.width ? item.width : 125">
  14. <!--其实可以在上面:prop="item.prop"就可以显示表单数据 这里设置插槽的方式话更加灵活 我们可以写样式-->
  15. <template slot-scope="scope">
  16. <span style="margin-left: 10px">{{ scope.row[item.prop] }}</span>
  17. </template>
  18. </el-table-column>
  19. <!--操作-->
  20. <el-table-column label="操作" min-width="180">
  21. <template slot-scope="scope">
  22. <el-button size="min" @click="handleEdit(scope.row)">编辑</el-button>
  23. <el-button size="min" type="danger" @click="handleDelete(scope.row)">删除</el-button>
  24. </template>
  25. </el-table-column>
  26. </el-table>
  27. <!--分页-->
  28. <el-pagination class="pager" layout="prev, pager, next" :total="config.total" :current-page.sync="config.page" @current-change="changePage" :page-size="20"></el-pagination>
  29. </div>
  30. </template>
  31. <script>
  32. // config分页数据,这里面至少包括当前页码 总数量
  33. export default {
  34. props: {
  35. tableData: Array,
  36. tableLabel: Array,
  37. config: Object
  38. },
  39. methods: {
  40. //更新
  41. handleEdit(row) {
  42. this.$emit('edit', row)
  43. },
  44. //删除
  45. handleDelete(row) {
  46. this.$emit('del', row)
  47. },
  48. //分页
  49. changePage(page) {
  50. this.$emit('changePage', page)
  51. }
  52. }
  53. }
  54. </script>

三、示例

这里展示用户管理组件(UserManage.vue),它使用了上面两个封装后的组件。

  1. <template>
  2. <div class="manage">
  3. <el-dialog :title="operateType === 'add' ? '新增用户' : '更新用户'" :visible.sync="isShow">
  4. <common-form :formLabel="operateFormLabel" :form="operateForm" ref="form"></common-form>
  5. <div slot="footer" class="dialog-footer">
  6. <el-button @click="isShow = false">取 消</el-button>
  7. <el-button type="primary" @click="confirm">确 定</el-button>
  8. </div>
  9. </el-dialog>
  10. <div class="manage-header">
  11. <el-button type="primary" @click="addUser">+ 新增</el-button>
  12. <common-form inline :formLabel="formLabel" :form="searchFrom">
  13. <el-button type="primary" @click="getList(searchFrom.keyword)">搜索</el-button>
  14. </common-form>
  15. </div>
  16. <!--依次是: 表格数据 表格标签数据 分页数据 列表方法 更新方法 删除方法-->
  17. <common-table :tableData="tableData" :tableLabel="tableLabel" :config="config" @changePage="getList()" @edit="editUser" @del="delUser"></common-table>
  18. </div>
  19. </template>
  20. <script>
  21. import CommonForm from '../../components/CommonForm'
  22. import CommonTable from '../../components/CommonTable'
  23. export default {
  24. components: {
  25. CommonForm,
  26. CommonTable
  27. },
  28. data() {
  29. return {
  30. operateType: 'add',
  31. isShow: false,
  32. tableData: [],
  33. tableLabel: [
  34. {
  35. prop: 'name',
  36. label: '姓名'
  37. },
  38. {
  39. prop: 'age',
  40. label: '年龄'
  41. },
  42. {
  43. prop: 'sexLabel',
  44. label: '性别'
  45. },
  46. {
  47. prop: 'birth',
  48. label: '出生日期',
  49. width: 200
  50. },
  51. {
  52. prop: 'addr',
  53. label: '地址',
  54. width: 320
  55. }
  56. ],
  57. config: {
  58. page: 1,
  59. total: 30,
  60. loading: false
  61. },
  62. operateForm: {
  63. name: '',
  64. addr: '',
  65. age: '',
  66. birth: '',
  67. sex: ''
  68. },
  69. operateFormLabel: [
  70. {
  71. model: 'name',
  72. label: '姓名',
  73. type: 'input'
  74. },
  75. {
  76. model: 'age',
  77. label: '年龄',
  78. type: 'input'
  79. },
  80. {
  81. model: 'sex',
  82. label: '性别',
  83. type: 'select',
  84. opts: [
  85. {
  86. label: '男',
  87. value: 1
  88. },
  89. {
  90. label: '女',
  91. value: 0
  92. }
  93. ]
  94. },
  95. {
  96. model: 'birth',
  97. label: '出生日期',
  98. type: 'date'
  99. },
  100. {
  101. model: 'addr',
  102. label: '地址',
  103. type: 'input'
  104. }
  105. ],
  106. searchFrom: {
  107. keyword: ''
  108. },
  109. formLabel: [
  110. {
  111. model: 'keyword',
  112. label: '',
  113. type: 'input'
  114. }
  115. ]
  116. }
  117. },
  118. methods: {
  119. getList(name = '') {
  120. this.config.loading = true
  121. // 搜索时,页码需要设置为1,才能正确返回数据,因为数据是从第一页开始返回的
  122. name ? (this.config.page = 1) : ''
  123. this.$http
  124. .get('/api/user/getUser', {
  125. params: {
  126. page: this.config.page,
  127. name
  128. }
  129. })
  130. .then(res => {
  131. this.tableData = res.data.list.map(item => {
  132. item.sexLabel = item.sex === 0 ? '女' : '男'
  133. return item
  134. })
  135. this.config.total = res.data.count
  136. this.config.loading = false
  137. })
  138. },
  139. addUser() {
  140. this.operateForm = {}
  141. this.operateType = 'add'
  142. this.isShow = true
  143. },
  144. editUser(row) {
  145. this.operateType = 'edit'
  146. this.isShow = true
  147. this.operateForm = row
  148. },
  149. confirm() {
  150. if (this.operateType === 'edit') {
  151. console.log(this.operateForm)
  152. this.$http.post('/api/user/edit', this.operateForm).then(res => {
  153. console.log(res.data)
  154. this.isShow = false
  155. this.getList()
  156. })
  157. } else {
  158. this.$http.post('/api/user/add', this.operateForm).then(res => {
  159. console.log(res.data)
  160. this.isShow = false
  161. this.getList()
  162. })
  163. }
  164. },
  165. delUser(row) {
  166. this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
  167. confirmButtonText: '确定',
  168. cancelButtonText: '取消',
  169. type: 'warning'
  170. })
  171. .then(() => {
  172. let id = row.id
  173. this.$http
  174. .get('/api/user/del', {
  175. params: {
  176. id
  177. }
  178. })
  179. .then(res => {
  180. console.log(res.data)
  181. this.$message({
  182. type: 'success',
  183. message: '删除成功!'
  184. })
  185. this.getList()
  186. })
  187. })
  188. .catch(() => {
  189. this.$message({
  190. type: 'info',
  191. message: '已取消删除'
  192. })
  193. })
  194. }
  195. },
  196. created() {
  197. this.getList()
  198. }
  199. }
  200. </script>
  201. <style lang="scss" scoped>
  202. @import '@/assets/scss/common';
  203. </style>
  1. 别人骂我胖,我会生气,因为我心里承认了我胖。别人说我矮,我就会觉得好笑,因为我心里知道我不可能矮。这就是我们为什么会对别人的攻击生气。
  2. 攻我盾者,乃我内心之矛(15)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/383444
推荐阅读
相关标签
  

闽ICP备14008679号