likes
comments
collection
share

element-ui table组件化,重新封装

作者站长头像
站长
· 阅读数 28

1、话不多说先看效果

主要实现功能:筛选:输入框、下拉框、时间;表格适用:多选、序号、排序、自定义、开关、链接可跳转、输入框、图片、自定义操作按钮(部分页面需要每行显示按钮不用所以大家按需添加)、常规操作按钮(每行操作按钮都相同无其他需求)、设置行背景色、分页element-ui table组件化,重新封装

2、本文部分原创,大框架是复制的https://blog.csdn.net/qq_37346639/article/details/115556605这个博客,因为懒的自己写😂,按照需求改为自己所需要格式

3、筛选组件代码

<template>
    <div>
      <ul class="row-list" v-if="screenConfig.searchShow">
        <li v-for="(item,index) in screenConfig.formItem" :key="index">
          <label v-if="item.type != 'operationBtn'">{{item.label}}:</label>
<!--          输入框-->
          <el-input v-if="item.type === 'input'" clearable v-model.trim="screenConfig.searchParams[item.prop]"
                    class="w215" size="small" :placeholder="item.placeholder"></el-input>
<!--          下拉框-->
          <el-select v-if="item.type === 'select'" filterable clearable v-model.trim="screenConfig.searchParams[item.prop]"
                     :placeholder="item.placeholder" size="small" :multiple="item.multiple" :filterable="item.filterable">
            <el-option v-for="selectItem in item.options" :key="selectItem[item.value]" :value="selectItem[item.value]"
                       :label="selectItem[item.leftLabel]" :disabled="selectItem.disabled">
              <span style="float: left">{{ selectItem[item.leftLabel] }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">{{ selectItem[item.rightLabel] }}</span>
            </el-option>
          </el-select>
<!--          时间选择器-->
          <el-date-picker v-if="item.type === 'datePicker'" clearable v-model="screenConfig.searchParams[item.prop]"
                          :type="item.dateType" size="small" :value-format="item.format" placeholder="请选择"
                          range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
          </el-date-picker>
<!--          自定义-->
          <slot v-if="item.type == 'custom'" name='customFilter'></slot>
          <!--          按钮-->
          <span v-if="item.type == 'operationBtn'" v-for="(operations, index) in item.operation" :key="index">
                        <el-button v-if="operations.isShow" :type="operations.btnType"  :icon="`iconfont ${operations.icon}`"
                       @click="screenBtn(operations)" class="screen-btn" :disabled="operations.disabled"
                       size="mini">{{operations.label}}
            </el-button>
                    </span>
        </li>
      </ul>
    </div>
</template>

<script>
  export default {
    name: "PublicFilter",
    props: {
      screenConfig: {
        type: Object,
        required: true
      },
    },
    data() {
      return {};
    },
    methods: {
      // 操作按钮
      screenBtn(data) {
        this.$emit("screenBtn",data)
      }
    },
  }
</script>

<style scoped lang="less">
.screen-btn {
  margin-right: 10px;
}
.row-list {
  li{
    margin-bottom: 15px;
    float: left;
    margin-right: 15px;
    min-height: 32px;
    line-height: 32px;
  }
}
</style>

4、表格组件代码

<template>
  <div>
    <el-table size="medium" :data="tableData" :stripe="false" :border="false" :fit="true"
              :header-cell-style="{background:columnObj.headerBgColor,color: columnObj.headerColor,height: columnObj.headerHigh}"
              :highlight-current-row="columnObj.highlight" :row-class-name="tableRowClassName"
              @row-click="rowClick" :row-style="tableRowStyle"  @sort-change="sortChange">
      <!-- 选择框是否开启,selectable控制是否单行禁用 -->
      <el-table-column v-if="columnObj.selection" type="selection" :selectable="selectable" :align="columnObj.align || 'center'"></el-table-column>
      <el-table-column v-if="columnObj.serialNumber" type="index" label="序号" :align="columnObj.align || 'center'" width="50"></el-table-column>
      <!-- 普通列 -->
      <el-table-column v-for="(column,columIndex) in columnObj.columnData" :key="columIndex" :prop="column.prop"
                       :label="column.label" :width="column.width" :fixed="column.fixed" :align="columnObj.align || 'center'"
                       :sortable="column.sortable" :index="columIndex" show-overflow-tooltip>
        <template slot-scope="{row,$index}">
          <!-- 默认展示 -->
          <span v-if="column.type == 'text'" :style="{color:row[column.colorName]}">
            {{row[column.prop]}}
          </span>
          <!-- 标签类型 -->
          <span v-if="column.type == 'tag'">
            <el-tag :type="row[column.tagType]">{{row[column.prop]}}</el-tag>
          </span>
          <!-- 自定义内容 -->
          <slot v-if="column.type == 'ownDefined'" name='ownDefined' :row="row,column"></slot>
          <!-- switch开关 -->
          <el-switch v-if="column.type == 'switch'" v-model="row[column.prop]"
                     :inactive-text="row[column.prop] ? column.openText:column.closeText"
                     @change="switchChange(row,$index,column.prop)"></el-switch>
          <!-- 图片展示 -->
          <el-image v-if="column.type == 'image'" style="width: 50px; height: 50px" :src="row[column.prop]" fit="cover" :preview-src-list="[row[column.prop]]"></el-image>
<!--          url-->
          <div v-if="column.type == 'url'">
            <a v-if="row[column.urlName]" :href="row[column.urlName]"  target="_blank" class="url">{{row[column.prop]}}</a>
            <span v-else>{{row[column.prop]}}</span>
          </div>
          <!-- 可编辑-->
          <el-input v-if="column.type == 'editRow'" v-model="row[column.prop]" :disabled="row[column.editRow]"
                    @blur="editInputBlur(row,$index,column.prop,columIndex)" size="mini"></el-input>
<!--           自定义操作按钮,每行不一样-->
          <span v-if="column.type == 'customAction'" v-for="(operations, index) in row[column.prop]" :key="index">
                        <el-button v-if="operations.isShow" type="text"
                       @click="rowOperation(row,$index,operations.type)" :style="{color:operations.color}"
                       size="small">{{operations.label}}
            </el-button>
                    </span>
<!--           常规操作按钮-->
          <span v-if="column.type == 'routineAction'" v-for="(operations, index) in column.operation" :key="index">
                        <el-button v-if="operations.isShow" type="text"
                       @click="rowOperation(row,$index,operations.type)" :style="{color:operations.color}"
                       size="small">{{operations.label}}
            </el-button>
                    </span>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div class="page_div" :style="{textAlign: pageObj.position || 'center'}" v-if="pageObj.show">
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
                     :hide-on-single-page="false" :current-page="pageObj.pageNo" :pager-count="7"
                     :page-sizes="[10, 15, 20, 30,50]" :page-size="pageObj.pageSize" background
                     layout="total,sizes,prev, pager, next" :total="pageObj.total">
      </el-pagination>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'public-table',
    props: {
      tableData: {
        type: Array,
        required: true
      },
      columnObj: {
        type: Object,
        required: true
      },
      pageObj: {
        type: Object,
        required: true
      }
    },
    data() {
      return {
      }
    },
    methods: {
      // 控制单行是否可用
      selectable(row, index) {
        if (row.switchs) {
          return true;
        }
        this.$emit("selectable", row, index)
      },
      // 操作按钮
      rowOperation(row, $index, now) {
        this.$emit("rowOperation", row, $index, now)
      },
      // switchChange调用
      switchChange(row, $index, prop) {
        this.$emit("switchChange", row, $index, prop);
      },
      // 行样式
      tableRowStyle({row}) {
        if(row.styleData) {
          return {'background': `${row.styleData.bgColor}`,'color':`${row.styleData.fontColor}`};
        }
      },
      // 行的 className 的回调方法
      tableRowClassName({row, rowIndex}) {
        row.rowIndex = rowIndex;
      },
      // 点击行
      rowClick(row, column, event) {
        this.$emit("rowClick", row, column, event);
      },
      // 可编辑input失去焦点
      editInputBlur(row, $index, prop, columIndex) {
        this.$emit('editInputBlur', row, $index, prop, columIndex);
      },
      // 远程排序
      sortChange({column, prop, order}) {
        // ascending上    descending下
        this.$emit('sortChange', column, prop, order);
      },
      // 条数变化
      handleSizeChange(e) {
        this.$emit('handleSizeChange', e);
      },
      // 页码变化
      handleCurrentChange(e) {
        this.$emit('handleCurrentChange', e);
      }
    }
  }
</script>
<style lang="less" scoped>
  .el-button {
    margin: 0 6px;
  }
  .page_div {
    padding: 15px 0;
  }
  .url {
    color: #3d8de0;
    cursor: pointer;
  }
  /deep/.el-table__body tr.current-row>td.el-table__cell {
    background-color: #a8b9cc;
  }
  /deep/.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
    color: #606266;
  }
</style>

5、全局引入组件

**main.js**页面全局引入组件或单页面引入看需求,我是全局引入

import { PublicTable,PublicFilter } from '@/components';

Vue.component(PublicTable.name,PublicTable);
Vue.component(PublicFilter.name,PublicFilter);

文件目类[图片上传失败...(image-70848a-1662602567621)]components>index.js

import PublicTable from '@/components/PublicTable';
import PublicFilter from '@/components/PublicFilter';

export {
  PublicTable,PublicFilter
};

6、父组件使用

<template>
  <div class="box">
    <el-card shadow="never">
      <public-filter :screenConfig="screenConfig" @screenBtn="screenBtn">
        <template  slot='customFilter'>
          <el-radio-group v-model="screenConfig.searchParams.aaa" class="radio">
            <el-radio :label="3">备选项</el-radio>
            <el-radio :label="6">备选项</el-radio>
            <el-radio :label="9">备选项</el-radio>
          </el-radio-group>
        </template>
      </public-filter>
    </el-card>
    <el-card shadow="never" class="mt-20">
      <public-table :tableData="tableData" :columnObj="columnObj" :pageObj="pageObj" @rowOperation="rowOperation"
                   @switchChange="switchChange" @editInputBlur="editInputBlur" @rowClick="rowClick"
                    @sortChange="sortChange"
                   @handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange">
        <template slot='ownDefined' slot-scope="{row,column}">
          <p>
            <span v-if="row.names" :class="`iconfont ${row.names.icon}`" :style="{fontSize: row.names.fontSize,color: row.names.color}"></span>
            {{row.name}}
          </p>
          <p>{{row.address}}</p>
        </template>
      </public-table>
    </el-card>
  </div>
</template>
<script>

  export default {
    data() {
      return {
        // 筛选配置
        screenConfig:{
          searchShow: true, //筛选是否显示
          formItem: [{
            type: "input",
            prop:'input',
            label: "姓名",
            placeholder:'请输入姓名'
          }, {
            type: "select",
            prop: "parkingType",
            label: "类型",
            value:"id",
            leftLabel:"name",
            rightLabel:"gender",
            multiple: false,
            filterable: true,
            options: [{
              id: '1',
              name: '张三',
              gender: '男',
            },{
              id: '2',
              name: '李四',
              disabled: true
            },{
              id: '3',
              name: '李四',
              gender: '女',
            }],
            placeholder:'请选择数据'
          }, {
            type: "datePicker",
            prop: "data",
            label: "导出时间",
            format: "yyyy-MM-dd", //数据格式'yyyy-MM-dd'、timestamp(时间戳)
            dateType: "datetimerange", //显示类型(常用类型daterange、date、datetime) year年、month月、date日期、dates多个日期、 week周、datetime日期和时间点、datetimerange日期和时间范围、 daterange日期范围、monthrange月份范围
            placeholder: '请选择',
          }, {
            type: "custom",
            prop: "aaa",
            label: "自定义筛选",
          }, {
            type: "operationBtn",
            prop: "data",
            operation: [{
              btnType: "primary", //primary蓝色、success绿色、warning橘黄、danger红色、 info灰色、text文本
              type: 'cx',
              label: "查询",
              isShow: true,
              disabled: false,
              icon: 'icon-cry',
            },{
              btnType: "danger", //primary蓝色、success绿色、warning灰色、danger橘黄、 info红色、text文本
              type: 'cz',
              label: "重置",
              isShow: true,
              disabled: true,
              icon:'icon-atm-away'
            }]
          }]
        },
        // 表头配置
        columnObj: {
          selection: true,// 选择框
          serialNumber: true,// 序号
          highlight: false,// 当前行是否高亮
          align: 'center',// 对齐方式
          headerBgColor: '',// 表头背景色
          headerColor: '',// 表头字体颜色
          headerHigh: '55px',// 表头高
          // columnObj
          // selection(是否有多选框):true显示,false隐藏
          // serialNumber(是否有序列号):true显示,false隐藏
          // align(行文字对其方式):left左,right右,center居中
          // highlight(当前行是否高亮)
          // headerColor(表头字体颜色)
          // headerHigh(表头高):小于55px没有效果
          // columnObj>columnData
          //type(列类型):text文本,ownDefined自定义 ,switch开关,url链接,editRow可编辑,image图片,customAction自定义操作,routineAction常规操作
          //prop(参数),label(列名),width(宽度)
          //sortable(是否支持排序):true开启排序,false关闭排序'custom'远程排序
          //openText,closeText(开关开启/关闭名称),urlName(url地址对应参数):参数为空时只展示文字不可跳转
          //editRow(当前行是否可编辑和type为editRow对应):false可编辑,true不可编辑
          //colorName 控制文字颜色字段名
          columnData: [{
            type:'text',
            prop: "school",
            label: "默认样式",
            width: "",
            colorName: "color",
          }, {
            type:'tag',
            prop: "tag",
            tagType: "tagType",
            label: "标签类型",
            width: "",
          }, {
            type:'text',
            prop: "id",
            label: "可以排序",
            width: "",
            sortable: true,
          }, {
            type:'ownDefined',
            prop: "aaa",
            label: "自定义内容",
            width: "",
          }, {
            type:'switch',
            prop: "switchs",
            label: "switch开关",
            width: "",
            openText: "打开", //type='switch' 打开时的文字描述
            closeText: "关闭", //type='switch' 关闭时的文字描述
          }, {
            type:'url',
            prop: "name2",
            label: "可跳转",
            urlName: "url", //type='url',跳转地址名称(按需返回)
            width: "",
          }, {
            type:'editRow',
            prop: "name",
            label: "可编辑",
            width: "",
            editRow: 'editRow',
          },{
            type:'image',
            prop: "img",
            label: "图片",
            width: "",
          }, {
            type:'customAction',
            label: "自定义操作",
            width: "180",
            prop: "operation",
          }, {
            type:'routineAction',
            label: "常规操作",
            width: "180",
            operation: [{
              type: "cg",
              label: "常规",
              color: '',
              isShow: true,
            }]
          }],
        },
        // 表格数据
        // editRow(可编辑行是否可操作true/false)
        // styleData(Object类型,行样式,背景色、字体颜色等)
        //operation(Array类型,表头type=‘customAction’时按钮配置):type类型,label按钮名,color按钮颜色,isShow是否显示(true/false),
        // tagType标签类型(success绿/info灰/warning橘黄/danger红/)返回空为默认值蓝色
        tableData: [{
          id: '1',
          school: '北京大学',
          name: '王小虎',
          tag: '标签一',
          tagType: 'success',
          names:{
            name: '王小虎',
            icon:'icon-phone',
            fontSize: '15px',
            color:"red",
          },
          editRow: true,
          address: '上海市普陀区金沙江路 1518 弄',
          switchs: true,
          img: '',
          name2: '张三',
          icon: 'icon-phone',
          // 行样式
          styleData: {
            bgColor: '#878787',
            fontColor: '#fff',
          },
          operation: [{
            type: "edit",
            label: "编辑",
            color: '#be147d',
            isShow: true,
          }, {
            type: "delete",
            label: "删除",
            color: 'red',
            isShow: false,
          }, {
            type: "see",
            label: "查看",
            color: '#d77000',
            isShow: true,
          }],
        }, {
          id: '2',
          school: '天津大学',
          name: '王小虎',
          tag: '标签二',
          tagType: '',
          names:{
            name: '王小虎2',
            icon:'icon-cry',
            fontSize: '18px',
            color:"blue",
          },
          address: '上海市普陀区金沙江路 1517 弄',
          switchs: true,
          img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
          name2: '李四',
          url:'https://www.baidu.com/',
        }, {
          id: '3',
          school: '北京体育',
          tag: '标签三',
          tagType: 'info',
          color: 'red',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄',
          switchs: false,
          name2: '王五',
          img: '',
          operation: [{
            type: "edit",
            label: "编辑",
            color: '#67C23A',
            isShow: true,
          }, {
            type: "delete",
            label: "删除",
            color: 'red',
            isShow: true,
          }, {
            type: "see",
            label: "查看",
            color: '',
            isShow: true,
          }]
        }, {
          id: '4',
          school: '河北师范大学',
          name: '王小虎',
          tag: '标签四',
          tagType: 'warning',
          address: '上海市普陀区金沙江路 1516 弄',
          switchs: true,
          name2: '赵六',
          url:'https://www.baidu.com/',
          img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
        }],
        //分页配置
        pageObj: {
          show: true, //是否显示
          position: "right", //位置
          total: 100,
          pageNo: 1,
          pageSize: 10
        },
      }
    },
    created(){
      this.$set(this.screenConfig,'searchParams',{})
    },
    methods: {
      screenBtn(data) {
      },
      rowOperation(row, $index, now) {
        console.log(row, $index, now)
      },
      switchChange(row, $index, prop) {
        console.log(row, $index, prop)
      },
      rowClick(row, column, event) {
        // 点击行触发,编辑点击的所在列,排除selection选择框
        // if (column.type != 'selection') {
        //   this.columnObj.columnData[column.index].editRow = row.rowIndex;
        // }
      },
      sortChange(column, prop, order) {
        // console.log(column, prop, order)
      },
      editInputBlur(row, $index, prop, columIndex) {
        // console.log(row, $index, prop, columIndex)
        // this.columnObj.columnData[columIndex].editRow = -1;
      },
      //页码变化
      handleCurrentChange(e) {
        this.pageObj.pageNo = e;
      },
      //条数变化
      handleSizeChange(e) {
        this.pageObj.pageSize = e;
        this.pageObj.pageNo = 1;
      },
    },
  }
</script>
<style>
.box {
  background: #f4f4f4;
  padding: 2% 1%;
  box-sizing: border-box;
}
</style>