vue3+el-table组件封装(代码部分)

790 阅读1分钟

承接上篇文章:vue3+el-table组件封装(理论部分)

1、publicTable组件

全部代码

<template>
  <!-- 公用表格 -->
  <div class="table-body">
    <div class="body">
      <div class="forms">
        <el-table
          ref="table"
          :data="tableData"
          :stripe="isStripe"
          :border="showBorder"
          row-key="Id"
          :height="tableHeight2 ? tableHeight2 : tableHeight"
          style="width: 100%"
          v-loading="isLoading"
          :highlight-current-row="showHighlight"
          element-loading-text="数据加载中..."
          :default-expand-all="false"
          :header-row-class-name="tableRowClassName"
          @expand-change="exChange"
          @current-change="handleCurrentChange"
          @selection-change="handleSelectionChange"
          @row-click="handleRowClick"
        >
          <!-- 是否有含有子内容的第一列 -->
          <el-table-column type="selection" v-if="showSelection === true">
          </el-table-column>
          <el-table-column type="expand" v-if="showChild === true">
            <slot name="expand-child"></slot>
          </el-table-column>
          <template v-for="(item, index) in tableHeaders" :key="index">
            <!--不带插槽的列-->
            <el-table-column
              :prop="item.field"
              :label="item.title"
              v-if="item.slotName == ''"
              :min-width="item.width"
              label-class-name="tes0"
              :show-overflow-tooltip="showTooltip"
            />
            <!--带插槽的列 有固定列的列-->
            <el-table-column
              v-else-if="item.slotName == 'td_ID' || item.slotName == 'td_Id'"
              :max-width="item.width > 0 ? item.width : 170"
              fixed="right"
              :prop="item.field"
              :label="item.title"
              label-class-name="tes0"
              :show-overflow-tooltip="showTooltip"
            >
              <template #default="scope">
                <slot :name="item.slotName" v-bind="scope"></slot>
              </template>
            </el-table-column>
            <!--带插槽的列-->
            <el-table-column
              v-else
              :prop="item.field"
              :label="item.title"
              :min-width="item.width"
              label-class-name="tes0"
              :show-overflow-tooltip="showTooltip"
            >
              <template #default="scope">
                <slot :name="item.slotName" v-bind="scope"></slot>
              </template>
            </el-table-column>
          </template>
        </el-table>
      </div>
      <!-- 分页 -->
      <div class="table-footer" v-if="showFooter">
        <div class="footer-left">
          {{ para.PageInfo.pageSize * (para.PageInfo.pageNum - 1) + 1 }}-{{
            para.PageInfo.pageNum * para.PageInfo.pageSize > total
              ? total
              : para.PageInfo.pageNum * para.PageInfo.pageSize
          }}
          / {{ total }}
        </div>
        <el-pagination
          :small="isSmall"
          background
          @current-change="handlePageChange"
          layout="prev, pager, next, jumper"
          :total="total"
          :page-size="para.PageInfo.pageSize"
          :pager-count="pagerCount"
        >
        </el-pagination>
      </div>
    </div>
  </div>
</template>

<script>
import { useSlots } from "vue";
export default {
  props: {
    tableHeight2: {
      type: String,
    },
    pagerCount: {
      type: Number,
      default: 5,
    },
    isSmall: {
      type: Boolean,
      default: false,
    },
    isStripe: {
      type: Boolean,
      default: true,
    },
    showHighlight: {
      type: Boolean,
      default: false,
    },
    showTooltip: {
      type: Boolean,
      default: true,
    },
    showFooter: {
      type: Boolean,
      default: true,
    },
    showBorder: {
      type: Boolean,
      default: true,
    },
    showChild: {
      type: Boolean,
      default: false,
    },
    showSelection: {
      type: Boolean,
      default: false,
    },
    tableHeaders2: {
      type: Array,
      default: function () {
        return [];
      },
    },
  },
  data() {
    return {
      slots: useSlots(), // 获取插槽信息
      tableHeaders: [], //表头数据
      tableData: [], //表格数据
      isLoading: true, // 表格的loading效果
      total: 0, // 总数
      para: {
        queryId: "",
        PageInfo: { pageNum: 1, pageSize: 10 },
        conditions: null,
      },
      tableHeight: "100%",
    };
  },
  emits: ["expand-change", "changePage", "selectRow", "selectionChange"], //vue3子传父需写
  methods: {
    //开启loading
    openLoadingStatus() {
      this.isLoading = true
    },
    //选中复选框
    handleSelectionChange(res) {
      this.$emit("selectionChange", res);
    },
    setCurrent(row) {
      this.$refs.table.setCurrentRow(row);
    },
    // 选中行
    handleCurrentChange(val) {
      this.$emit("selectRow", val);
    },
    //点击行
    handleRowClick(val){
        this.$emit('clickRow',val.value)
    },
    // 获取表格数据 父组件获取
    getTData(para, res) {
      this.para = para;
      this.changeTableHeight();
      this.tableData = res.rows;
      this.total = res.total;
      this.tableHeaders = this.tableHeaders2;
      this.tableHeaders.forEach((col) => {
        let _slotName = ''
        if (col.title === '操作' && col.field === 'TDM') {
          _slotName = "td_CAOZUO";
        } else {
          _slotName = "td_" + col.field;
        }
        if (typeof this.slots[_slotName] === "function") {
          // 有插槽
          col.slotName = _slotName;
        } else {
          // 没有插槽
          col.slotName = "";
        }
      });
      this.isLoading = false;
    },
    async exChange(row, rowList) {
      this.$emit("expand-change", row, rowList);
    },
    // 分页
    handlePageChange(val) {
      if (this.tableHeaders2.length === 0) {
        this.para.PageInfo.pageNum = val;
        this.getDataList(this.para);
      } else {
        this.isLoading = true;
        this.$emit("changePage", val);
      }
    },
    //给表头加下划线
    tableRowClassName({ rowIndex }) {
      if (rowIndex === 0) {
        return "header-row";
      }
      return "";
    },
    toggleRowExpansion(row) {
      this.$refs.table.toggleRowExpansion(row);
    },
  },
};
</script>

<style>
.tes0 {
  color: #000000;
}
.el-table__expanded-cell[class*="cell"] {
  padding: 0px 50px;
}
.el-table .header-row th {
  /* background: rgb(235, 161, 161)!important; */
  border-bottom: 1px #ebe8e8 solid;
  background: #f2f4f4;
}
.el-table .header-row th > .cell {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.el-table th,
.el-table td {
  padding: 6px 0;
  background: #ffffff;
}
</style>

<style scoped>
.body {
  height: 100%;
  display: flex;
  justify-content: space-between;
  flex-direction: column;
}
.tes {
  color: #3c8dbc;
  cursor: pointer;
}

.el-table tr {
  color: #000000;
}

.table-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* height: 50%; */
  padding: 7px;
  /* bottom:10%; */
  overflow: hidden;
  border-right: 1px solid #ebeef5;
  border-left: 1px solid #ebeef5;
  border-bottom: 1px solid #ebeef5;
  background: #ffffff;
}
.footer-left {
  float: left;
  font-size: 13px;
  color: var(--el-text-color-regular);
}
.el-pagination {
  float: right;
}

.el-table .header-row th {
  /* background: rgb(235, 161, 161)!important; */
  border-bottom: 1px #ebe8e8 solid;
  background: #f2f4f4 !important;
}
.el-table .header-row th > .cell {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
:deep(.el-table.danger-row) {
  color: rgb(194, 15, 15);
}
.el-pagination :deep(.btn-prev .el-icon),
.el-pagination :deep(.btn-next .el-icon) {
  display: inline-block;
}
</style>

2、组件引用

<template>
  <PublicTable
    ref="publicTable"
    :tableHeaders2="tableHeaders2"
    @changePage="handlePageChange"
  >
    <template #td_Id="scope">
      <el-button size="mini" type="text" @click="editRows(scope.row)"
        >修改</el-button
      >
      <el-button size="mini" type="text" @click="deleteData(scope.row)"
        >删除</el-button
      >
    </template>
  </PublicTable>
</template>

<script>

import PublicTable from '@/components/table/PublicTable.vue'
export default {
  name: 'xx',
  components: {
    PublicTable
  },
  data() {
    return {
      tableHeaders2: [], //表头,
      para: {
        queryId: 'company_list',
        PageInfo: { pageNum: 1, pageSize: 10 },
        conditions: null,
      },
    }
  },
  methods: {
    editRows(row) {
      //编辑操作
    },
    
    deleteData(row) {
      //删除操作
    },
    //获取表头数据
    getLoadData() {
      let me = this
      this.$ajax
        .get('url')
        .then(function (response) {
          if (response.data.isSuccess) {
            me.tableHeaders2 = response.data.data
            me.getDataList(me.para)
          } else {
            console.log(response.data.errorMessage)
          }
        })
    },
    //获取表格数据
    async getDataList(para) {
      this.para = para
      let me = this
      var res = await this.$ajax.post('url')
      res = JSON.parse(res.data.data)
      me.$refs.publicTable.getTData(me.para, res);//这里传递的res的值 上篇文章有说明;
    },

    // 分页
    handlePageChange(val) {
      this.para.PageInfo.pageNum = val
      this.getDataList(this.para)
    },
  },
  mounted() {
    this.getLoadData();
  },
}
</script>

3、总结

我这基本上可是把我现在使用的照搬过来了,可以好好参考下。 效果图:

image.png