el-table表格封装(包括switch,操作栏,元素带点击事件,区分颜色显示,分页,暂无数据等)

效果图(字段较多,所以分段截图展示):

表格组件public-table.vue

<template>
  <div class="public-table">
    <!-- 具体使用方法参考public-table-demo.vue -->
    <div class="list-table-cont">
      <div class="list-table">
        <el-table
          @selection-change="handleSelectionChange"
          :data="tableData"
          :stripe="false"
          :border="false"
          :fit="true"
          :show-header="true"
          :highlight-current-row="true"
          v-loading="columObj.loading"
          :row-class-name="tableRowClassName"
          class="public-table-cont"
        >
          <!-- 选择框是否开启,selectable控制是否单行禁用 -->
          <el-table-column
            v-if="columObj.selection"
            type="selection"
            :selectable="columObj.selectable"
            width="60"
          />
          <!-- 普通列 -->
          <el-table-column
            v-for="(column, columIndex) in columObj.columnData"
            :key="columIndex"
            :prop="column.prop"
            :label="column.label"
            :minWidth="column.width"
            :fixed="column.fixed"
            :align="column.align || 'left'"
            :sortable="column.sortable"
            :index="columIndex"
            show-overflow-tooltip
          >
            <template slot="header">
              {{ column.label }}
              <el-popover
                v-show="column.isQuestion"
                placement="top-start"
                title=""
                width="200"
                trigger="hover"
                :content="column.questionCont"
              >
                <i class="el-icon-question" slot="reference"></i>
              </el-popover>
            </template>
            <template slot-scope="{ row, $index }">
              <!-- 默认数据展示,类型为text:true -->
              <span
                v-if="column.text && column.editRow != $index"
                :style="`color:${column.textColor}`"
              >
                {{ row[column.prop] || '—' }}
              </span>
              <!-- 对象展示,类型为status:true -->
              <span v-if="column.status && row[column.prop]">{{
                row[column.prop].msg || '—'
              }}</span>
              <!-- 自定义内容,数据需要通过自己特殊处理的,类型为slot:true -->
              <slot v-if="column.slot" :name="row[column.prop]" :row="row">
                <span v-html="column.format(row, $index)"></span>
              </slot>
              <!-- 自定义格式返回,比如状态,时间拼接等,类型为ownDefined:true-->
              <span v-if="column.ownDefined" :style="column.formatColor && column.formatColor(row)">
                {{ column.format(row, $index) || '—' }}
              </span>
              <!--数据有点击事件,可进行点击跳转,弹框等操作,类型为clickable:true -->
              <span
                v-if="column.clickable"
                :class="column.textClass"
                @click="column.itemClick(row, $index)"
                class="click-style"
              >
                {{ column.format(row, $index) || '—' }}
              </span>
              <!-- 返回的数据是简单的数组,类型为isArray:true -->
              <span v-if="column.isArray">
                <span v-for="(item, index) in row[column.prop]" :key="index">
                  {{ row[column.prop].length - 1 !== index ? item + ',' : item || '—' }}
                </span>
              </span>
              <!-- 既有默认的返回数据,又有自定义的可点击内容,类型为textClick:true -->
              <span v-if="column.textClick">
                <span>{{ row[column.prop] || '—' }}</span>
                <span class="blue-line">|</span
                ><span
                  class="click-style"
                  @click="column.itemClick(row, $index)"
                  :class="column.textClass"
                  >{{ column.textCont || '—' }}</span
                >
              </span>
              <!-- switch开关,打开时值为true ,关闭时值为false  -->
              <el-switch
                v-if="column.switch"
                v-model="row[column.prop]"
                :inactive-text="row[column.prop] ? column.openText : column.closeText"
                @change="switchChange(row, $index)"
              />
              <!-- switch开关,打开时值为1 ,关闭时值为0 -->
              <el-switch
                v-if="column.switchNum"
                :active-value="1"
                :inactive-value="0"
                v-model="row[column.prop]"
                :inactive-text="row[column.prop] ? column.openText : column.closeText"
                @change="switchChange(row, $index)"
              />

              <!-- 单个图片展示,类型为image:true -->
              <div class="logo-box flex-column-center-center" v-if="column.image">
                <el-image
                  class="logo"
                  :class="column.imgStyle"
                  :src="row[column.prop]"
                  :preview-src-list="[row[column.prop]]"
                  alt="图片"
                />
              </div>
              <!-- 图片数组 -->
              <div class="logo-box flex-column-center-center" v-if="column.imageArr">
                <el-image
                  class="logo"
                  :class="column.imgStyle"
                  v-if="row[column.prop].length > 0"
                  :src="row[column.prop][0]"
                  :preview-src-list="row[column.prop]"
                  alt="图片"
                />
              </div>
              <!-- 操作按钮 -->
              <span
                v-show="column.isOperation"
                v-for="(operations, index) in column.operation"
                :key="index"
              >
                <el-button
                  :icon="operations.icon"
                  :type="operations.type"
                  @click="operations.buttonClick(row, $index)"
                  :class="
                    operations.format && operations.format(row)
                      ? operations.disabledClass
                      : operations.styleClass
                  "
                  :disabled="operations.format && operations.format(row)"
                  size="small"
                  >{{ operations.label }}</el-button
                >
                <span v-show="operations.dividerLine" class="divider-line">|</span>
              </span>
            </template>
          </el-table-column>
          <!-- 自定义操作栏,与isOperation不能同时存在-->
          <slot name="tableOperations"></slot>
          <!-- 暂无数据 -->
          <div slot="empty" class="empty">
            <img :src="`${ASSET_HOST}/event/activity_null.png`" />
            <span>暂无数据</span>
          </div>
        </el-table>
      </div>
      <!-- 分页 -->
      <!-- noPagination为true时不显示分页,默认为false,可不传此参数 -->
      <div class="pagination-panel flex-end" v-show="!columObj.noPagination">
        <div class="total-pages">
          共
          <span>{{ pageObj.total }}</span> 条数据
        </div>
        <div class="total-pages" :style="{ textAlign: pageObj.position || 'center' }">
          <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="pageObj.page"
            :page-size="pageObj.pageSize"
            layout="sizes, prev, pager, next,jumper"
            :total="pageObj.total"
          >
          </el-pagination>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'public-table', //共用table组件
  directives: {
    // 自定义指令,用于可编辑input自动获取焦点
    focus: {
      inserted: function (e) {
        e.querySelector('input').focus();
      },
    },
  },
  props: {
    tableData: {
      type: Array,
      required: true,
    },
    columObj: {
      type: Object,
      required: true,
    },
    //columObj.type(如果为""空,就不会加载多选框,或者index编号),lazy(是否支持懒加载)
    //columnData.columType(列类型,可选text(默认为普通文字模式),input(input可编辑框),switch(switch开关),image(图片),operation(操作按钮))
    //prop(参数),label(列名),width(宽度),align(对齐方式),sortable(是否支持排序)
    //如果为操作列,则需要填写需要的操作按钮,类型为Object。type(按钮样式,参考el—botton类型),label(按钮文字)icon(参考el-icon),color(字体颜色),buttonClick为点击后调用的方法名称
    pageObj: {
      type: Object,
      required: true,
    },
  },

  methods: {
    // switchChange调用
    switchChange(row, $index, prop) {
      this.$emit('switchChange', row, $index, prop);
    },
    // 帮助点击行,获取点击的下标
    tableRowClassName({ row, rowIndex }) {
      row.rowIndex = rowIndex;
    },
   // 选择的数据
    handleSelectionChange(val) {
      this.$emit("handleSelectionChange", val);
    },
    // 条数变化
    handleSizeChange(e) {
      this.$emit('handleSizeChange', e);
    },
    // 页码变化
    handleCurrentChange(e) {
      this.$emit('handleCurrentChange', e);
    },
  },
};
</script>
<style lang='scss' scoped>
.public-table {
  .el-button {
    margin: 0 6px;
  }
  .text-underline {
    text-decoration: underline;
  }
  .click-style {
    cursor: pointer;
  }
  .text-color {
    color: #0064ff;
  }
.red-text {
  color: red !important;
}

.blue-text {
  color: rgba(0, 100, 255, 1) !important;
}

.disabled-text {
  color: #999 !important;
}
  /deep/ .el-input__inner {
    border: none;
  }

  /deep/ .el-image__inner {
    height: 50px;
  }
  // switch左边文字颜色
  /deep/ .el-switch__label--left {
    color: #606266;
  }
.flex-column-center-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
  .logo-box {
    width: 50px;
    height: 50px;
    /deep/.el-image__inner {
      height: auto !important;
    }
    .logo {
      width: 50px;
      height: 50px;
      display: inline-block;
      object-fit: cover;
    }
    .logo-style {
      height: 40px !important;
    }
    .logo-list-style {
      width: 80px !important;
      height: 80px !important;
    }
  }
}
</style>

public-table-demo.vue页面引用组件 

<template>
  <div class="public-table-demo">
    <div class="public-table-demo-titles flex-between">
      <div class="public-table-demo-titles-left">封装表格使用示例</div>
    </div>
    <div class="public-table-demo-cont">
      <!-- 表格(直接复制这个组件到对应文件) -->
      <public-table
        :tableData="tableData"
        :columObj="columObj"
        :pageObj="pageObj"
        @switchChange="switchChange"
        @handleSelectionChange="handleSelectionChange"
        @handleSizeChange="handleSizeChange"
        @handleCurrentChange="handleCurrentChange"
      >

        <!-- 放开注释代码并删除columnData中的isOperation为true的操作列则为自定义操作栏 -->
        <!-- <div slot="tableOperations">
          <el-table-column prop="status" width="200" fixed="right" label="操作">
            <template slot-scope="scope">
              <el-button
                type="text"
                size="small"
                @click.native="editBanner(scope.row)"
                >编辑</el-button
              >
            </template>
          </el-table-column>
        </div> -->
     
</public-table>
    </div>
  </div>
</template>
  
  <script>
export default {
  name: 'public-table-demo',
  components: {
    publicTable: () => import('@/components/common/public-table.vue'),
  },
  data() {
    return {
      tableData: [
        {
          cont: '普通数据',
          setColor: '设置为蓝色',
          isQuestion: '标题带问号',
          logo: 'https://tuoluohuodong.oss-cn-shang hai.aliyuncs.com/digital_system/tuoluoicon.png',
          logoList: [
            'https://tuoluohuodong.oss-cn-shang hai.aliyuncs.com/digital_system/30841d9826d04081961102138d606ac3.jpeg',
            'https://tuoluohuodong.oss-cn-shang hai.aliyuncs.com/digital_system/8e696633c92249ce806d417c26c630f5.jpeg',
          ],
          isOpenSwitch: true,
          isOpenSwitchNum: 0,
          status: 1,
          startTime: '2022-03-31 00:00:00',
          endTime: '2023-03-31 00:00:00',
          sex: 1,
          booth: null,
          exhibition: null,
          clickValue: '可点击跳转',
          productInfoVOList: [
            { id: '3523435726235345363', productSn: '419225611403', auditStatus: 1 },
            { id: '3523435726235345364', productSn: '673929573648', auditStatus: 2 },
          ],
          venueVal: ['B', 'C', 'C'],
          numDetail: 99,
          objmsg: {
            msg: '对象啊',
          },
        },
        {
          cont: '普通数据',
          setColor: '设置为蓝色',
          isQuestion: '标题带问号',
          logo: 'https://tuoluohuodong.oss-cn-shang hai.aliyuncs.com/digital_system/tuoluoicon.png',
          logoList: [
            'https://tuoluohuodong.oss-cn-shang hai.aliyuncs.com/digital_system/d49e5941cc834a28ad0b3cd730bf01ea.jpg',
            'https://tuoluohuodong.oss-cn-shang hai.aliyuncs.com/digital_system/b03a4a6605f540ae9148c008a7bc8193.jpg',
          ],
          isOpenSwitch: false,
          isOpenSwitchNum: 1,
          status: 2,
          startTime: '2022-03-01 12:00:00',
          endTime: '2023-03-01 18:00:00',
          sex: 2,
          booth: '展馆号',
          exhibition: '展位号',
          clickValue: '可点击跳转',
          productInfoVOList: [
            { id: '3578388750457094201', productSn: '019109210492', auditStatus: -1 },
          ],
          venueVal: ['A', 'C', 'D'],
          numDetail: 10,
          objmsg: {
            msg: '对象啊',
          },
        },
      ], //列表数据

      columObj: {
        selection: true, // 是否显示选择框
        // noPagination:true,//是否显示分页(为true不显示,默认显示分页则不需要此参数)
        /***
         * column列,
         * columType(列类型,可选text(默认为普通文字模式),
         * switch(switch开关,后台返回false或true),
         * switchNum(switch开关,后台返回0或1),
         * image(图片),
         * operation(操作按钮)
         * textColor(文本颜色,不传则是默认颜色)
         * ownDefined(自定义返回内容)
         * clickable(内容可点击操作)
         * isArray(数组)
         * textClick(又有普通内容又有可点击操作内容)
         ***/
        /***
         * prop(参数),
         * label(列名),
         * width(宽度),
         * align(对齐方式,默认左对齐),
         * sortable(是否支持排序)
         * format(自定义值)
         * formatColor(自定义值的颜色,需要则设置)
         * textClass(样式设置)
         * itemClick(内容点击事件)
         * textCont(有点击事件的固定内容)
         ***/
        columnData: [
          {
            text: true,
            prop: 'cont',
            label: '默认',
            width: '150',
          },
          {
            text: true,
            textColor: '#0064ff',
            prop: 'setColor',
            label: '设置颜色',
            width: '150',
          },
          {
            text: true,
            prop: 'isQuestion',
            label: '显示问号',
            width: '120',
            isQuestion: true, //是否显示问号tips
            questionCont: '提示内容啊啊', //问号显示的内容
          },
          {
            image: true,
            prop: 'logo',
            label: 'logo展示',
            width: '120',
            imgStyle: 'logo-style',
          },
          {
            imageArr: true,
            prop: 'logoList',
            label: '多张图',
            width: '120',
            imgStyle: 'logo-list-style',
          },
          {
            switch: true,
            prop: 'isOpenSwitch',
            label: 'switch按钮(后台返回false或true)',
            width: '300',
          },
          {
            switchNum: true,
            prop: 'isOpenSwitchNum',
            label: 'switch按钮(后台返回0或1)',
            width: '260',
          },
          {
            ownDefined: true,
            prop: 'status',
            label: '状态(自定义颜色)',
            width: '180',
            format: (row) => {
              let text = '';
              switch (row.status) {
                case 1:
                  text = '绿色';
                  break;
                case 2:
                  text = '黄色';
                  break;
                default:
                  return '—';
              }
              return text;
            },
            formatColor: (row) => {
              switch (row.status) {
                case 1: {
                  return { color: '#04b935' };
                }
                case 2: {
                  return { color: '#ffab4f' };
                }
                default: {
                  return { color: '#ee423d' };
                }
              }
            },
          },
          {
            slot: true,
            prop: 'productInfoVOList',
            label: '数组',
            width: '300',
            format: (row) => {
              const { productInfoVOList } = row;
              const auditStatus = { '-1': '报名失败', 1: '报名成功', 2: '审核中' };
              let rowEl = productInfoVOList.map((item) => {
                return `<div> ${item.productSn}(${auditStatus[item.auditStatus]})</div>`;
              });
              let rowElVal = rowEl.toString();
              return rowElVal.replace(/,/g, ''); //去掉逗号
            },
          },
          {
            ownDefined: true,
            prop: 'startTime',
            label: '时间拼接',
            width: '380',
            format: (row) => {
              return row.startTime + '~' + row.endTime;
            },
          },
          {
            ownDefined: true,
            prop: 'sex',
            label: '性别(后台返回1和2)',
            width: '200',
            format: (row) => {
              let text = '';
              switch (row.sex) {
                case 1:
                  text = '男';
                  break;

                case 2:
                  text = '女';
                  break;

                default:
                  text = '—';
              }
              return text;
            },
          },
          {
            clickable: true,
            prop: 'startTime',
            itemClick: this.addBooth,
            label: '两个字段且带点击事件',
            width: '200',
            textClass: 'text-underline',
            format: (row) => {
              return row.exhibition || row.booth
                ? `${row.exhibition || '暂无'} | ${row.booth || '暂无'}`
                : '点击设置展位';
            },
          },
          {
            clickable: true,
            prop: 'clickValue',
            itemClick: this.goUrl,
            textClass: 'text-color',
            label: '带点击事件',
            width: '140',
            format: (row) => {
              return row.clickValue;
            },
          },
          {
            isArray: true,
            prop: 'venueVal',
            label: '数组',
            width: '140',
          },
          {
            textClick: true,
            prop: 'numDetail',
            itemClick: this.goPage,
            textClass: 'text-color',
            textCont: '点击的文案',
            label: '内容与点击事件',
            width: '180',
          },
          {
            status: true,
            prop: 'objmsg',
            label: 'obj类型',
            width: '140',
          },

          /***
           * 如果为操作列,则需要填写需要的操作按钮,类型为Object。
           * type(按钮样式,参考el—botton类型),
           * label(按钮文字)
           * icon(参考el-icon),
           * color(字体颜色),
           * isShow(是否显示按钮),
           * dividerLine(是否显示分隔线)
           * styleClass(按钮样式,不传则为默认)
           ***/
          {
            fixed: 'right',
            isOperation: true,
            label: '操作',
            width: '140',
            operation: [
              {
                type: 'text',
                label: '编辑',
                icon: '',
                buttonClick: this.editTable,
                disabledClass: 'disabled-text ',
                dividerLine: true,
                format:(row) => {
                  return row.sex==1
                },//禁用条件
              },
              {
                type: 'text',
                label: '删除',
                icon: '',
                styleClass: 'red-text',
                buttonClick: this.delTable,
              },
            ],
          },
        ],
      },
      pageObj: {
        total: 0,
        page: 1,
        pageSize: 10,
      }, //分页对象
    };
  },

  methods: {
    // 设置占位
    addBooth(row, $index) {
      console.log(row, '设置');
    },
    // 跳转链接
    goUrl(row, $index) {
      console.log(row, '点击跳转');
    },
    // 跳转详情
    goPage(row, $index) {
      console.log(row, '跳转详情');
    },
    // 编辑事件
    editTable(row, $index) {
      console.log(row, $index, '编辑');
    },
    // 删除事件
    delTable(row, $index) {
      console.log(row, $index, '删除');
    },
    // 行改变事件
    rowOperation(row, $index) {
      console.log(row, $index);
    },
    // cahnge改变事件
    switchChange(row, $index) {
      console.log(row, $index, 'switch');
    },
    // 选中的条数
    handleSelectionChange(val) {
      console.log(val, "选中的数据");
    },
    // 获取数据的方法
    getData() {},
    // 改变页数
    handleCurrentChange(val) {
      this.pageObj.page = val;
      this.getData();
    },
    // 改变页码
    handleSizeChange(val) {
      this.pageObj.pageSize = val;
      this.getData();
    },
  },
};
</script>
  <style lang='scss' scoped>
.public-table-demo {
  background: #ffffff;
  padding: 0.32rem 0.2rem 0.16rem 0.2rem;
  // border: 1px solid #dcdfe6;
  border-radius: 4px;
  .public-table-demo-titles-left {
    font-size: 24px;
    font-weight: bold;
  }
}
</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值