基于elementUI 封装数据表格(table+pagination)

47 阅读1分钟
<template>
  <div class="container" ref="tableData">
    <m-loading
      class="main"
      :loading="loading">
      <el-table
        v-bind="$attrs"
        v-on="$listeners"
        :row-key="rowKey"
        border
        style="width: 100%;"
        :data="data"
        @sort-change="sortChange"
        @selection-change="selectionChange"
      >
        <template v-for="(item) in columns">
          <el-table-column
            :key="item.prop || item.type"
            v-bind="item"
            :header-align="item.headerAlign || 'center'"
            show-overflow-tooltip>
            <template v-if="item.slotName" v-slot="scope">
              <slot :name="item.slotName" :data="scope"></slot>
            </template>
          </el-table-column>
        </template>
      </el-table>
      <template v-if="data.length">
        <el-pagination
          v-if="hasPagination"
          class="pagination"
          background
          :layout="layout"
          :page-size.sync="pagination.limit"
          :total="pagination.total"
          :current-page.sync="pagination.page"
          @size-change="sizeChange"
          @current-change="currentChange"
        />
      </template>

    </m-loading>
  </div>
</template>

<script>
export default {
  name: 'index',
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    // 表格行数据的唯一键
    rowKey: {
      type: String,
      default: 'id'
    },
    // 列配置
    columns: {
      type: Array,
      default: () => []
    },
    // 分页
    pagination: {
      type: Object,
      default: () => {}
    },
    // 表格数据
    data: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      // 元素高度
      height: 0
    }
  },
  watch: {

  },
  computed: {
    // 是否显示分页
    hasPagination() {
      return !!this.pagination;
    },
    // 分页布局
    layout() {
      const layout = 'total, sizes, prev, pager, next, jumper';
      return this.pagination?.layout || layout;
    },
  },
  methods: {
    /**
     * 监听pageSize 改变时会触发
     * @param {String} limit 每页数据条数
     * */
    sizeChange(limit) {
      this.pagination.page = 1;
      this.pagination.limit = limit;
      this.$emit('pagination-change');
    },
    /**
     * 监听分页改变
     * @param {String} page 当前页数
     * */
    currentChange(page) {
      this.pagination.page = page;
      this.$emit('pagination-change');
    },
    /**
     * 监听表格的排序条件
     * @param {string} prop 排序字段
     * @param {string} order 排序顺序:ascending 正序 descending 倒序
     * */
    sortChange({ prop, order }) {
      const sortObj = {
        sort: '',
        order: ''
      }
      if (order) {
        sortObj.sort = prop;
        sortObj.order = order === 'ascending' ? 'asc' : 'desc';
      }
      this.$emit('sortChange', sortObj)
    },
    /**
     * 监听表格选中
     * */
    selectionChange(val) {
      this.$emit('selectionChange', val);
    }
  },
  // 组件挂载后
  mounted() {
    this.height = this.$refs.tableData.offsetHeight;
  }
}
</script>

<style lang="scss" scoped>
  .container {
    width: 100%;
    flex: 1;
  }
  .main {
    background: #fff;
    padding: 15px;
  }
  .pagination {
    text-align: right;
    margin-top: 20px;
  }
</style>