当前位置:   article > 正文

Vue3.0使用Element-ui制作table组件,操作列动态渲染按钮_vue table组件

vue table组件

        大家好,我是一个8年前端开发经验的新博主(实战react方向较多),最近两年互联网行业动荡,工作不稳定,想积累点自己的项目实践经验以备不时之需。第一弹!分享一下最近使用vue3.0二次封装过的el-table组件,带有分页功能,以及操作列按动态数据有条件渲染!希望可以帮助各位在职前端小伙伴解决一些实际问题。

       下一弹分享自定义搜索表单组件<SearchForm/>,喜欢的记得点个赞哦~

知识点:

1、二次封装el-table,减少重复写很多标签

2、table表格自带翻页页签pagination

3、序号列按当前页累加计算

4、操作列按数据有条件渲染

直接先看效果图:(前提先安装UI组件库:npm element-plus --save)

代码比较多,原因是我写的比较全,有经验的可以直接看关键的地方!!

首先,看二次封装过的Table组件代码

  1. <!--
  2. * @Author: Cocoon_xu
  3. * @LastEditTime: 2024-02-18 16:41:12
  4. * @Description: 二次封装表格组件,带翻页控件
  5. -->
  6. <template>
  7. <!-- 表格 -->
  8. <el-table
  9. :data="tableData"
  10. :border="border"
  11. :stripe="stripe"
  12. v-loading="loading"
  13. style="width: 100%; overflow-x: auto;"
  14. @selection-change="selectionChange"
  15. >
  16. <!-- 复选框 -->
  17. <el-table-column v-if="isSelectabled" type="selection" width="50" />
  18. <template v-for="(column,index) in tableColunms" :key="index">
  19. <!-- 文字不需要特殊显示 -->
  20. <el-table-column
  21. :type="column.type"
  22. :prop="column.prop"
  23. :label="column.label"
  24. :fixed="column.fixed || true"
  25. :sortable="column.sortable || false"
  26. :show-overflow-tooltip="column.overHidden || false"
  27. :width="column.width"
  28. :min-width="column.minWidth || '50px'"
  29. :align="column.align || 'center'"
  30. :formatter="column.formatter"
  31. >
  32. <!-- <template #default="scope" >
  33. <span v-if="scope.column.type !=='index'">{{ scope.row[column.prop] ? scope.row[column.prop] : "" }}</span>
  34. <span v-if="scope.column.type ==='index'">{{ (pagination.pageNum-1) * pagination.pageSize + scope.$index + 1}}</span>
  35. </template> -->
  36. </el-table-column>
  37. </template>
  38. <!-- 操作列插槽 -->
  39. <el-table-column
  40. label="操作"
  41. fixed="right"
  42. align="center"
  43. >
  44. <template #default="scope">
  45. <!-- 当操作按钮少于3个,建议使用mode:'inline',默认为'dropdown'模式 -->
  46. <table-dropdown
  47. :actionColumns='()=>actionColumns(scope)'
  48. :scope="scope"
  49. :mode="actionMode || 'dropdown'"
  50. />
  51. </template>
  52. </el-table-column>
  53. </el-table>
  54. <!-- 分页 -->
  55. <div class="pagination">
  56. <el-pagination
  57. v-model:page-size="pagination.pageSize"
  58. v-model:current-page="pagination.pageNum"
  59. :total="total"
  60. :layout="layout"
  61. :page-sizes="pageSizesArr"
  62. @size-change="sizeChange"
  63. @current-change="currentChange"
  64. />
  65. </div>
  66. </template>
  67. <script setup>
  68. import { defineProps, defineEmits } from 'vue';
  69. import TableDropdown from '@/components/TableDropdown/dropdown.vue'
  70. const emits = defineEmits(['sizeChange', 'currentChange'])
  71. const props = defineProps({
  72. tableData:{
  73. type: Array,
  74. default:[]
  75. },
  76. tableColunms:{
  77. type: Array,
  78. default: []
  79. },
  80. actionColumns:{
  81. type: Function,
  82. default:() => {}
  83. },
  84. actionMode:{
  85. type: String,
  86. default: 'dropdown'
  87. },
  88. opColunms:{
  89. type: Object,
  90. default: {}
  91. },
  92. border:{ // 是否带有纵向边框
  93. type: Boolean,
  94. default: false
  95. },
  96. loading:{
  97. type: Boolean,
  98. default: false
  99. },
  100. isSelectabled: { // 是否带有复选框
  101. type: Boolean,
  102. default: false
  103. },
  104. pagination: {
  105. type: Object,
  106. default: () => {
  107. return {pageSize: 10, pageNum: 1}
  108. }
  109. },
  110. pageSizesArr:{
  111. type: Array,
  112. default: () => {
  113. return [10,20,30,50]
  114. }
  115. },
  116. stripe: { // 是否为斑马纹 table
  117. type: Boolean,
  118. default: false
  119. },
  120. total: {
  121. type: Number,
  122. required: true,
  123. default: 0
  124. },
  125. layout:{
  126. type: String,
  127. default: "total, sizes, prev, pager, next, jumper"
  128. }
  129. })
  130. // 触发选择框
  131. const selectionChange = (val) => {
  132. console.log(val)
  133. }
  134. // 切换分页size
  135. const sizeChange = (val) => {
  136. emits('sizeChange', val)
  137. }
  138. // 切换分页
  139. const currentChange = (val) => {
  140. emits('currentChange', val)
  141. }
  142. </script>
  143. <style lang="scss">
  144. /* .el-table .warning-row {
  145. --el-table-tr-bg-color: var(--el-color-warning-light-9);
  146. }
  147. .el-table .success-row {
  148. --el-table-tr-bg-color: var(--el-color-success-light-9);
  149. } */
  150. .pagination{
  151. margin: 15px auto;
  152. display: flex;
  153. justify-content: center;
  154. }
  155. .el-table{
  156. .el-table__header .cell{
  157. color: #000;
  158. }
  159. }
  160. </style>

我们可以看到Table组件里调用了TableDropdown,也是我自定义的一个组件,用于表格的操作列按表格数据有条件渲染成不同的按钮。下面为此组件的代码:

  1. <!--
  2. * @Author: Cocoon_xu
  3. * @LastEditTime: 2024-02-18 16:38:25
  4. * @Description: 表格操作列表
  5. -->
  6. <script setup>
  7. import { defineProps } from 'vue';
  8. const props = defineProps({
  9. actionColumns:{
  10. type: Function,
  11. default: () => {}
  12. },
  13. scope: {
  14. type: Object,
  15. default: {}
  16. },
  17. mode: {
  18. type: String,
  19. default: 'dropdown'
  20. }
  21. })
  22. </script>
  23. <template>
  24. <template v-if="mode === 'inline'">
  25. <el-button
  26. v-for="(item,index) in actionColumns(scope)"
  27. text
  28. :key="index"
  29. :icon="item.icon"
  30. :disabled="item.disabled"
  31. :style="{marginLeft:0, color: item.color}"
  32. @click="(e)=>{
  33. e.preventDefault();
  34. let row = JSON.parse(JSON.stringify(scope.row))
  35. item.event(row);
  36. }"
  37. >
  38. {{ item.label }}
  39. </el-button>
  40. </template>
  41. <template v-else>
  42. <el-dropdown>
  43. <span class="el-dropdown-link">
  44. <el-icon color="#409EFC"><Menu/></el-icon>
  45. </span>
  46. <template #dropdown>
  47. <el-dropdown-menu>
  48. <el-dropdown-item
  49. v-for="(item, index) in actionColumns(scope)"
  50. :key="index"
  51. :icon="item.icon"
  52. :disabled="item.disabled"
  53. @click="(e)=>{
  54. e.preventDefault();
  55. let row = JSON.parse(JSON.stringify(scope.row))
  56. item.event(row);
  57. }"
  58. >
  59. <span>{{ item.label }}</span>
  60. </el-dropdown-item>
  61. </el-dropdown-menu>
  62. </template>
  63. </el-dropdown>
  64. </template>
  65. </template>
  66. <style lang="scss">
  67. .table-menu{
  68. background: transparent;
  69. .el-menu-item{
  70. padding: 0;
  71. height: 24px;
  72. line-height: 24px;
  73. }
  74. }
  75. </style>

最后,就是调用组件的使用

  1. <!--
  2. * @Author: Cocoon_xu
  3. * @LastEditTime: 2024-02-18 16:38:25
  4. * @Description: 组件调用
  5. -->
  6. <template>
  7. <div class="table-box">
  8. <common-table
  9. :loading="loading"
  10. :tableColunms="tableColunms"
  11. :actionColumns="actionColumns"
  12. :tableData="tableData"
  13. :pagination="pagination"
  14. :total="total"
  15. :stripe="true"
  16. :isSelectabled="false"
  17. @currentChange="handleCurrentChange"
  18. @sizeChange="handleSizeChange"
  19. ></common-table>
  20. </div>
  21. </template>
  22. <script setup>
  23. import { ref, onMounted, h } from 'vue';
  24. import CommonTable from '@/components/Table/index.vue';
  25. const loading = ref(false)
  26. const tableData = ref([])
  27. const total = ref(0)
  28. const pagination = ref({
  29. pageSize: 10,
  30. pageNum: 1
  31. })
  32. const tableColunms = [
  33. {
  34. label:'序号',
  35. width: 80,
  36. formatter:(row, columm, cellValue, index) => {
  37. return (pagination.value.pageNum-1) * pagination.value.pageSize + index + 1
  38. }
  39. },{
  40. label:'标题',
  41. prop:'title',
  42. minWidth: 120,
  43. overHidden: true
  44. },{
  45. label:'发布人',
  46. prop:'sendByName',
  47. },{
  48. label:'审核状态',
  49. prop:'submitStatus',
  50. minWidth: 70,
  51. formatter: (row, column, cellValue, index) => {
  52. if(cellValue === '1'){
  53. return h('span',{class:'draft'},'草稿')
  54. }else if(row.auditStatus === 'active'){
  55. return h('span',{class:'waitExamine'},'待审核')
  56. }else if(row.auditStatus === 'completed'){
  57. return h('span',{class:'pass'},'已通过')
  58. }else if(row.auditStatus === 'terminated'){
  59. return h('span',{class:'error'},'审批终止')
  60. }else if(row.auditStatus === 'rejected'){
  61. return h('span',{class:'error'},'被退回')
  62. }else{
  63. return '--'
  64. }
  65. }
  66. }
  67. ]
  68. // 操作列按钮
  69. const actionColumns = (scope) =>{
  70. let btns = [{
  71. label:'查看',
  72. type:'check',
  73. icon:'View',
  74. color:'#409EFC',
  75. disabled: false,
  76. event:(row) => {
  77. console.log(row)
  78. detail(row)
  79. }
  80. }];
  81. if(scope.row.auditStatus == 1 || (scope.row.auditStatus == 'rejected')){
  82. btns.push({
  83. label:'编辑',
  84. type:'edit',
  85. icon:'Edit',
  86. color:'#409EFC',
  87. disabled: false,
  88. event:(row) => {
  89. console.log(row)
  90. }
  91. })
  92. }
  93. if((scope.row.sendStatus == 0 && scope.row.auditStatus != 'completed'))){
  94. btns.push({
  95. label:'删除',
  96. type:'delete',
  97. icon:'Delete',
  98. color:'#409EFC',
  99. disabled: false,
  100. event:(row) => {
  101. console.log(row)
  102. }
  103. })
  104. }
  105. return btns;
  106. }
  107. // 切换当前分页
  108. const handleCurrentChange = (val) => {
  109. pagination.value = {
  110. pageNum: val,
  111. pageSize: pagination.value.pageSize
  112. }
  113. getConListInfoPagefn();
  114. }
  115. // 切换分页size
  116. const handleSizeChange = (val) => {
  117. pagination.value = {
  118. pageNum: 1,
  119. pageSize: val
  120. }
  121. getConListInfoPagefn();
  122. }
  123. </script>

代码部分结束!希望对你有所帮助!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/684246
推荐阅读
相关标签
  

闽ICP备14008679号