elementui的table的组件封装

效果如图:

1、ETable,封装的子组件

<template>
  <div class="table-conatianer">
    <div class="flex">
      <div class="table">
        <el-table border
                  :data="data.records">
          <el-table-column v-if="checkbox"
                           fixed
                           type="selection"
                           width="50px"
                           align="center"></el-table-column>
          <el-table-column v-if="orderNum"
                           fixed
                           type="index"
                           label="序号"
                           width="50px"
                           align="center">
          </el-table-column>
          <el-table-column v-if="operateEdit"
                           fixed
                           label="编辑"
                           width="50px"
                           align="center">
            <template slot-scope="scope">
              <i class="el-icon-edit-outline"
                 @click="operatorBtn(scope.row, 'edit')"></i>
            </template>
          </el-table-column>
          <el-table-column v-if="operateDel"
                           fixed
                           label="删除"
                           width="50px"
                           align="center">
            <template slot-scope="scope">
              <i class="el-icon-delete"
                 @click="operatorBtn(scope.row, 'delete')"></i>
            </template>
          </el-table-column>
          <template v-for="(item,index) in columns">
            <slot v-if="item.slotLabel"
                  :name="item.slotLabel"></slot>
            <el-table-column v-else
                             :key="index"
                             v-bind="item"
                             align="center"></el-table-column>
          </template>
        </el-table>
        <div class="bottom"
             v-if="pagination">
          <div>
            <slot name="leftBottom"></slot>
          </div>
          <div>
            <el-pagination @size-change="handleSizeChange"
                           @current-change="handleCurrentChange"
                           :current-page="listFilter.page"
                           :page-sizes="rows"
                           :page-size="listFilter.rows"
                           layout="total, sizes, prev, pager, next, jumper"
                           :total="data.total">
            </el-pagination>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    checkbox: { // 是否可勾选
      type: Boolean,
      default: true
    },
    orderNum: { // 是否显示序号
      type: Boolean,
      default: true
    },
    operateEdit: { // 是否显示编辑
      type: Boolean,
      default: true
    },
    operateDel: { // 是否显示删除
      type: Boolean,
      default: true
    },
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    data: {
      type: Object,
      default: () => {
        return {}
      }
    },
    pagination: {
      type: Boolean,
      default: true
    },
    listFilter: {
      type: Object,
      default: () => { }
    }
  },
  data: () => {
    return {
      rows: [20, 30, 50]
    }
  },
  created () {

  },
  methods: {
    operatorBtn (row, status) {
      if (status == 'edit') {
        this.$emit('handlEdit', row)
      } else {
        this.$emit('handlDelete', row.id)
      }
    },
    // 每页多少条
    handleSizeChange (val) {
      console.log(val)
      this.$emit('handleSizeChange', val)
    },
    // 当前多少页
    handleCurrentChange (val) {
      console.log(val)
      this.$emit('handleCurrentChange', val)
    }
  }
}
</script>
<style lang="scss" scoped>
.table-conatianer {
  width: 100%;
  height: 100%;
  .flex {
    display: flex;
    .tree {
      height: 100%;
      overflow-y: scroll;
    }
    .table {
      display: flex;
      flex-direction: column;
      .bottom {
        display: flex;
        justify-content: space-between;
      }
    }
  }
}
</style>

复选框,序号,编辑,删除默认都是显示的,表格底部的左侧还留有一个插槽,如果需要添加什么可以直接添加。

2、父组件调用子组件,需要传列表名称,props参数,也可以传其它的elementui的table行的参数,比如,width,fixed等。如果需要对参数进行自定义,那么使用slot插槽

<el-table-column slot="联系人"
                       label="联系人">
        <template v-slot="{row}">
          <span style="color:red">{{row.contactperson}}</span>
        </template>
      </el-table-column>

对应子组件里的

<slot v-if="item.slotLabel" :name="item.slotLabel"></slot>

父组件调用子组件:

<template>
  <div>
    <e-table :data="resultData"
             :columns="columns"
             :listFilter="listFilter"
             @handlEdit="handlEdit"
             @handlDelete="handlDelete"
             @handleSizeChange="handleSizeChange"
             @handleCurrentChange="handleCurrentChange">
      <el-table-column slot="联系人"
                       label="联系人">
        <template v-slot="{row}">
          <span style="color:red">{{row.contactperson}}</span>
        </template>
      </el-table-column>
      <template v-slot:操作>
        <el-table-column label="操作">
          <template v-slot="{row}">
            <el-button :data-id="row.id">添加</el-button>
          </template>
        </el-table-column>
      </template>

    </e-table>
  </div>
</template>
<script>
import ETable from '@/components/ETable.vue'
import { organization } from '@/framework/api/index'
export default {
  components: { ETable },
  data () {
    return {
      resultData: {},
      listFilter: {
        page: 1,
        rows: 20
      },
      columns: [
        {
          label: '名称',
          prop: 'name'
        },
        {
          label: '编码',
          prop: 'code'
        },
        {
          label: '上级机构',
          prop: 'parentName'
        },
        {
          label: '地址',
          prop: 'address',
          width: 150
        },
        {
          slotLabel: '联系人'
        },
        {
          slotLabel: '操作'
        }
      ]
    }
  },
  created () {
    this.getData()
  },
  methods: {
    getData () {
      this.showTableLoading()
        .then(_ => {
          if (this.organizationId) {
            return organization.getlist({ ...this.listFilter }, this.organizationId)
          } else {
            return organization.list({ ...this.listFilter })
          }
        })
        .then(res => {
          this.resultData = res.data
        })
    },
    showRow (row) {
      console.log(row)
    },
    handlEdit (row) {
      console.log(row)
      alert('编辑')
    },
    handlDelete (id) {
      console.log(id)
      alert('删除')
    },
    // 当前页多少条
    handleSizeChange (val) {
      this.listFilter.rows = val
      this.getData()
    },
    // 当前第几页
    handleCurrentChange (val) {
      this.listFilter.page = val
      this.getData()
    }
  }
}
</script>

3、如果想实现展开行,如图,需要添加type:expand

子组件,主要是这一部分

<el-table border
                  :data="data.records">
          <el-table-column v-if="orderNum"
                           fixed
                           type="index"
                           label="序号"
                           width="50px"
                           align="center">
          </el-table-column>
          <el-table-column v-if="expand.length"
                           type="expand">
            <template v-slot="props">
              <el-form label-position="left"
                       inline
                       class="table-expand">
                <el-form-item v-for="(item,index) in expand"
                              :key="index">
                  <label class="labelName">{{item.label}}</label>
                  <span v-if="item.func"
                        v-html="item.func(props.row[item.prop])"></span>
                  <span v-else>{{props.row[item.prop]}}</span>
                </el-form-item>
              </el-form>
            </template>
          </el-table-column>
          <template v-for="(item,index) in columns">
            <slot v-if="item.slotLabel"
                  :name="item.slotLabel"></slot>
            <el-table-column v-else
                             :key="index"
                             v-bind="item"
                             align="center"></el-table-column>
          </template>
        </el-table>


....
props:{
...
expand: {
      type: Array,
      default: () => []
    }
}

在父组件,调用子组件的时候,则还需要传expand

expand: [
        {
          label: '名称',
          prop: 'name'
        },
        {
          label: '编码',
          prop: 'code',
          func: (val) => {
            switch (val) {
              case '1':
                return '四川'
              default:
                return '其他'
            }
          }
        },
        {
          label: '上级机构',
          prop: 'parentName'
        },
        {
          label: '地址',
          prop: 'address'
        },
        {
          label: '上级机构',
          prop: 'parentName'
        },
        {
          label: '地址',
          prop: 'address'
        }
      ]

父组件传:expand="expand"

<e-table :data="resultData"
             :columns="columns"
             :listFilter="listFilter"
             :tree="true"
             :expand="expand"
             @handlEdit="handlEdit"
             @handlDelete="handlDelete"
             @handleSizeChange="handleSizeChange"
             @handleCurrentChange="handleCurrentChange">
      <el-table-column slot="联系人"
                       label="联系人">
        <template v-slot="{row}">
          <span style="color:red">{{row.contactperson}}</span>
        </template>
      </el-table-column>
      <template v-slot:操作>
        <el-table-column label="操作">
          <template v-slot="{row}">
            <el-button :data-id="row.id">添加</el-button>
          </template>
        </el-table-column>
      </template>

    </e-table>

 

### 如何封装 ElementUI Plus 表格组件 #### 封装目标 为了提高代码的可维护性和重用性,可以创建一个自定义表格组件封装ElementUI Plus中的`<el-table>`组件。这不仅简化了页面开发过程,还使得配置项更加统一和易于管理。 #### 创建基础结构 首先,在Vue项目中新建一个名为`CustomTable.vue`文件作为自定义表格组件的基础模板[^1]: ```vue <!-- CustomTable.vue --> <template> <div class="custom-table"> <!-- 使用element plus 的 table 组件并传递属性 --> <el-table :data="tableData" style="width: 100%" v-bind="$attrs"> <slot></slot> <!-- 插槽用于放置列定义 --> </el-table> </div> </template> <script setup lang="ts"> import { ref, defineProps } from 'vue'; // 定义props接收父级传入的数据源和其他参数 const props = defineProps({ data: { type: Array, default() { return []; }, } }); let tableData = ref(props.data); </script> ``` 此部分实现了基本的功能,即接受外部数据并通过插槽支持内部列定义的灵活性[^2]。 #### 增强功能与最佳实践 为了让这个组件更加强大且灵活,可以在原有基础上增加一些实用特性,比如分页、筛选以及排序等功能。通过监听事件或设置默认为来增强用户体验[^3]: ```javascript // 在 script 中添加更多逻辑处理 watch(() => props.data, (newVal) => { tableData.value = newVal; }, { immediate: true }); defineEmits(['sort-change', 'filter-change']); ``` 同时也可以考虑加入加载状态显示、错误提示等机制以应对网络请求失败等情况的发生。 对于样式方面,则可以通过CSS变量或者scoped CSS的方式来进定制化设计,确保不同应用场景下的外观一致性[^4]。 #### 实际应用案例 当需要在一个新的视图里展示带有特定需求(如固定表头、多选框等)的表格时,只需简单引入该自定义组件即可快速实现所需效果: ```html <CustomTable :data="usersList"> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column prop="age" sortable label="年龄"></el-table-column> ... </CustomTable> ``` 这样既减少了重复编码的工作量又提高了整体项目的质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LLL_LH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值