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>

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ElementUItable 组件提供了非常丰富的功能和接口,但是在实际项目中,我们经常需要对其进二次封装,以满足自己的业务需求。下面是一个简单的 ElementUI table 的二次封装示例: ```vue <template> <el-table :data="tableData" :height="height" :max-height="maxHeight" :stripe="stripe" :border="border" :fit="fit" :show-header="showHeader" :highlight-current-row="highlightCurrentRow" :row-class-name="rowClassName" :row-style="rowStyle" :cell-class-name="cellClassName" :cell-style="cellStyle" :header-row-class-name="headerRowClassName" :header-row-style="headerRowStyle" :header-cell-class-name="headerCellClassName" :header-cell-style="headerCellStyle" :row-key="rowKey" @select="handleSelect" @select-all="handleSelectAll" @selection-change="handleSelectionChange" @cell-mouse-enter="handleCellMouseEnter" @cell-mouse-leave="handleCellMouseLeave" @cell-click="handleCellClick" @cell-dblclick="handleCellDblClick" @row-click="handleRowClick" @row-contextmenu="handleRowContextMenu" @row-dblclick="handleRowDblClick" @header-click="handleHeaderClick" @header-contextmenu="handleHeaderContextMenu" @sort-change="handleSortChange" @filter-change="handleFilterChange" > <slot></slot> </el-table> </template> <script> export default { name: "MyTable", props: { tableData: { type: Array, default: () => [] }, height: { type: [Number, String], default: "" }, maxHeight: { type: [Number, String], default: "" }, stripe: { type: Boolean, default: true }, border: { type: Boolean, default: true }, fit: { type: Boolean, default: true }, showHeader: { type: Boolean, default: true }, highlightCurrentRow: { type: Boolean, default: true }, rowClassName: { type: Function, default: () => undefined }, rowStyle: { type: Function, default: () => undefined }, cellClassName: { type: Function, default: () => undefined }, cellStyle: { type: Function, default: () => undefined }, headerRowClassName: { type: Function, default: () => undefined }, headerRowStyle: { type: Function, default: () => undefined }, headerCellClassName: { type: Function, default: () => undefined }, headerCellStyle: { type: Function, default: () => undefined }, rowKey: { type: [String, Function], default: "" } }, methods: { handleSelect(selection, row) { this.$emit("select", selection, row); }, handleSelectAll(selection) { this.$emit("select-all", selection); }, handleSelectionChange(selection) { this.$emit("selection-change", selection); }, handleCellMouseEnter(row, column, cell, event) { this.$emit("cell-mouse-enter", row, column, cell, event); }, handleCellMouseLeave(row, column, cell, event) { this.$emit("cell-mouse-leave", row, column, cell, event); }, handleCellClick(row, column, cell, event) { this.$emit("cell-click", row, column, cell, event); }, handleCellDblClick(row, column, cell, event) { this.$emit("cell-dblclick", row, column, cell, event); }, handleRowClick(row, event, column) { this.$emit("row-click", row, event, column); }, handleRowContextMenu(row, event) { this.$emit("row-contextmenu", row, event); }, handleRowDblClick(row, event) { this.$emit("row-dblclick", row, event); }, handleHeaderClick(column, event) { this.$emit("header-click", column, event); }, handleHeaderContextMenu(column, event) { this.$emit("header-contextmenu", column, event); }, handleSortChange({ column, prop, order }) { this.$emit("sort-change", { column, prop, order }); }, handleFilterChange(filters) { this.$emit("filter-change", filters); } } }; </script> ``` 这里我们定义了一个名为 `MyTable` 的组件,并将其 props 与 ElementUI table 组件的 props 一一对应。在组件的模板中,我们使用了 `<slot></slot>`,表示组件的插槽,这样可以让用户在使用组件时自定义表格的列和内容。在组件的方法中,我们将 ElementUI table 的事件通过 `$emit` 的方式向上传递,这样可以使得组件的使用更加灵活。 使用这个组件时,我们只需要在父组件中引入 `MyTable` 组件,并将需要的 props 和插槽传入即可: ```vue <template> <my-table :table-data="tableData" :stripe="false" :highlight-current-row="false" @row-click="handleRowClick" > <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="年龄" prop="age"></el-table-column> <el-table-column label="地址" prop="address"></el-table-column> </my-table> </template> <script> import MyTable from "@/components/MyTable"; export default { name: "MyPage", components: { MyTable }, data() { return { tableData: [ { name: "张三", age: 18, address: "北京市" }, { name: "李四", age: 20, address: "上海市" }, { name: "王五", age: 22, address: "广州市" } ] }; }, methods: { handleRowClick(row) { console.log(row); } } }; </script> ``` 这样,我们就完成了一个简单的 ElementUI table 的二次封装,并且可以在父组件中灵活使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LLL_LH

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

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

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

打赏作者

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

抵扣说明:

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

余额充值