el-table二次封装表格组件

在日常开发后端管理系统项目中,用于展示数据多会用表格进行展示,这样我们可以把相同的部分处理出来,二次封装一个基于elementUI中的el-table封装一个简单的表格组件,进行多页面的数据展示的复用。

首先第一步肯定要引入elementUI组件库,我们可以使用全局引入和局部引入两种的方式

elementUI具体使用方法可以参考elementUI官网:

Element - The world's most popular Vue UI framework

这边个人推荐使用局部引入,这样可以减少项目的体积

引入之后,接下来我们就可以进行表格的二次封装了:

这个表格有多选框、内容、状态栏、升降序、图片、操作功能

子组件template部分:

<!-- 表格组件 -->    
<template>
  <el-table
    :data="data"
    ref="refTable"
    style="width: 100%"
    :row-key="rowKeyField"
    highlight-current-row
    :row-class-name="rowClassName"
    @select="handleSelection"
    @select-all="handleSelectionAll"
    @selection-change="handleSelectionChange"
    @sort-change="changeTableSort"
    @row-click="handleRowClick">
    <el-table-column
      v-if="showSelect"
      type="selection"
      width="55"
      align="center">
      <!-- //TODO showSelect:表格组件是否带多选框类型:带或不带 -->
    </el-table-column>
    <el-table-column
      align="center"
      v-for="item in columns"
      v-if="typeof item.show === 'undefined' ? true : item.show"
      :key="item.prop"
      :prop="item.prop"
      :label="item.label"
      :width="item.width"
      :sortable="item.sortable ? 'custom': false"
      :formatter="item.formatter">
    </el-table-column>
    <el-table-column v-if="showStatus" label="状态" align="center">
      <!-- // TODO showStatus:是否带状态开关 -->
      <template slot-scope="scope">
        <el-switch
          v-model="scope.row.status"
          active-value="0"
          inactive-value="1"
          @change="handleStatusChange(scope.row)">
        </el-switch>
      </template>
    </el-table-column>
    <el-table-column v-if="showImage" :label="imageName ? imageName :         
     '图片'" align="center" width="300">
      <template slot-scope="scope">
        <!-- 使用 imagePropertyName 映射到 imageUrl -->
        <el-image
          v-for="item in scope.row[imagePropertyName]"
          :key="item.index"
          style="width: 75px; height: 75px; margin-left: 5px;"
          :src="item"
          :preview-src-list="scope.row[imagePropertyName]"
        >
          <div
            slot="placeholder"
            class="image-slot"
            style="width: 75px; height: 75px"
          >
          <img src="@/assets/images/logging.gif" alt="" style="width: 75px; height: 75px" />
          </div>
        </el-image>
      </template>
    </el-table-column>
    <el-table-column
      v-if="showHandle"
      fixed="right"
      label="操作"
      width="150"
      align="center">
      <!-- //TODO showHandle:是否带操作栏 -->
      <template slot-scope="scope">
        <slot :item="scope.row"></slot>
      </template>
    </el-table-column>
  </el-table>
</template>

template部分的多选框、状态改变、图片展示、操作栏使用v-if判断是否显示,父组件传入Boolean值选择是否需要,使用示例请看父组件template部分

如果想针对不同角色或状态使表格数据展示不同时,可在父组件的tableColumns中传入show属性来让子组件判断是否展示

在表格中展示图片,需要在父组件中是图片路径转化为数组,并传入图片名

一般表格都会需要操作栏,那么我们使用插槽在子组件中对操作栏进行自定义,父组件中使用插槽添加自己想要的按钮,例子见代码中详情按钮

有时候会需要使用formatter解析表格中的部分参数(对时间进行格式化处理、金额加 $ 符号、后端返回状态对它进行转义展示),需要在子组件中定义formatter方法,让它使用父组件中传入的formatter函数即可,具体可看父组件data中的tableColumns

子组件script部分:

<script>
export default {
  props: {
    data: {
      type: Array,
      required: true,
    },
    columns: {
      type: Array,
      required: true,
    },
    rowKeyField: {
      type: String,
      required: false
    },
    // 图片展示属性名
    imagePropertyName: {
      type: String,
      required: false,
    },
    // 图片名
    imageName: {
      type: String,
      required: false,
    },
    showSelect: {
      type: Boolean,
      default: false,
    },
    showHandle: {
      type: Boolean,
      default: false,
    },
    showStatus: {
      type: Boolean,
      defalut: false,
    },
    showImage: {
      type: Boolean,
      defalut: false,
    },
  },
  methods: {
      //升降序
    changeTableSort(column){
      this.$emit("tableSort", column);
    },
    // 清空选择的值
    clearSelect() {
      this.$refs.refTable.clearSelection();
    },
    // 根据返回的数据满足过滤条件行高亮显示
    rowClassName: function ({ row, rowIndex }) {
      let data = "";
      this.$emit(
        "row-class-name",
        {
          row: row,
          rowIndex: rowIndex,
        },
        (val) => {
          data = val;
        }
      );
      return data; //属性名必须返回一个string
    },
    handleRowClick(row, column) {
      this.$emit("RowClick", row, column);
    },
      // 选中触发事件
      handleSelection(selection, row){
        this.$emit("selection", selection,row);
      },
      // 全选
      handleSelectionAll(selection){
        this.$emit("selectionAll", selection);
      },
      // 多选框
      handleSelectionChange(val) {
        this.$emit("selectionData", val);
      },
      // 状态开关
      handleStatusChange(row) {
      let text = row.status === "0" ? "启用" : "停用";
      this.$confirm('确认要"' + text + '"吗?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.msgSuccess(text + "成功");
          // console.log(row);
          this.$emit("statusData", row);
        })
        .catch(function () {
          row.status = row.status === "0" ? "1" : "0";
        });
    },
  },
};
</script>
<style lang="scss" scoped>
.el-image {
  ::v-deep .image-slot {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    color: #909399;
    font-size: 30px;
  }
</style>

子组件在data中规定父组件传递给子组件数据的类型,默认值等

子组件添加一些基础方法,把值传递给父组件,例如点击多选框后,触发子组件中复选框方法,利用$emit子传父自定义方法名,把选中数据传递给父组件,父组件中调用 @selectionData="getData"

父组件template部分:

<template>
  <div class="app-container">
    <Table
      ref="childTable"
      :data="tableData"
      :columns="tableColumns"
      showSelect
      showHandle
      showStatus
      showImage
      v-loading="loading"
      :imagePropertyName="pictureName"
      :imageName="imageName"
      @selection="getSelect" 
      @selectionAll="getSelectAll" 
      @selectionData="getSelectData" 
      @row-class-name="tableRowClassName">
        <template slot-scope="{ item }">
            <el-button @click="handleTableClick(item)" type="text" size="small">
                详情
            </el-button>
        </template>
    </Table>
  </div>
</template>

父组件sccript部分:

<script>
import * as Apis from "@/api/comparison/result/index";
import Table from "@/components/DataTable/index"; // 引入组件
import { dateFormat } from "@/utils/index"; // 时间处理函数
export default {
  components: {  // 使用子组件
    Table: Table,
  },
  data() {
    return {
      imageName: '证据', // 展示图片名称
      pictureName: 'claimReasonPicture', // 图片属性名称
      queryParams: {
        id: null,
        customerNo: "", // 客户编号
        contrastResult: "", // 客户状态查询
        outOrderNos: [], // 订单号
        trackNumbers: [], // 运单号
      },
      // 加载中遮罩层
      loading: false,
      tableData: [],
      tableColumns: [
        { prop: "customerNo", label: "客户编号", width: "150" },
        { prop: "outOrderNo", label: "客户订单号", show: false },
        { prop: "trackNumber", label: "运单号" },
        {
          prop: "priceTotal",
          label: "总计",
          width: "100",
          show: false,
          formatter: function (row, column, cellValue, index) {
            if (row.priceTotal) {
              return `$${row.priceTotal}`;
            }
          },
        },
        { prop: "importTime", label: "时间", formatter: dateFormat },
        {
          prop: "contrastResult",
          label: "状态",
          formatter: function (row, column, cellValue, index) {
            switch (row.contrastResult) {
              case 0:
                return "已打印";
              case 1:
                return "未打印";
              case -1:
                return "运输中";
              case -2:
                return "已取消";
              default:
                break;
            }
          },
        },
      ],
      ],
    };
  },
  methods: {
    // 选择框勾选中
    getSelect(selection, row) {
      console.log(selection, row);
    },
    // 选择框全选
    getSelectAll(selection) {
      console.log(selection);
    },
    getSelectData(selection) {
      console.log(selection);
    },
    async getList() {
      this.loading = true;
      const data = await Apis.contrastDetail(this.queryParams);
      console.log(data);
      this.loading = false;
      this.total = data.total;
      this.tableData = data.rows;
    },
    // 详情按钮
    handleTableClick(row) {
      console.log(row, "当前点击行中的数据");
    },
    // 行加类名加颜色
    tableRowClassName(obj, callback) {
      if (obj.row.children) {
        callback("success-row");
      } else {
        callback("");
      }
    },
  },
  created() {
    this.getList()
  },
};
</script>

在父组件data中tableColumns传入formatter方法,就可以对部分数据进行解析、处理。

以上就是基于el-table做的一个简单地二次封装,可以满足基础表格的使用,建议收藏文章,后续会继续完善,更加完美!

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值