El-Table的二次封装

记录一下在对el-tabel进行简单封装并实现行内编辑,单元格合并等功能


    <el-table

      id="iTable"

      v-loading.iTable="options.loading"//是否添加表格loading加载动画

      :data="list"//数据列

      :stripe="options.stripe"// 是否添加表格loading加载动画

      ref="multipleTable"// 是否支持列表项选中功能

      border

      :default-sort="{order: 'descending'}"

      @selection-change="handleSelectionChange"

      @filter-change="filterchange"

      :header-cell-style="rowClass"//多级表头控制样式

      :header-cell-class-name="headerStyle"//表头样式

      :row-class-name="tableRowClassName"//行样式

      :span-method="objectSpanMethod"//合并单元格

      :height="height"//高度

      size="small"

      :row-style="{height:'30px'}"

      :cell-style="{padding:'0px'}"

      @row-click="rowclick"//行点击事件

      @row-dblclick="dblclick"//双击

      @row-contextmenu="contmenuclick"//右键

      @cell-click="cellclick"//单元格事件

    >

      <template v-if="columns.show">//是否为多级,如果为多级,另一个组件循环(代码放下面)

        <my-column v-for="(item,index) incolumns.data" :key="index" :col="item">

      <template v-else>

        <template v-for="(column, index) incolumns">

            :prop="column.prop"

            :key="column.label"

            :label="column.label"

            :align="column.align"

            :min-width="column.width"

            :fixed="column.fixed"

            :filters="column.filters"

            sortable

          >

            <template slot-scope="scope">

              <template v-if="!column.render">

                <template v-if="column.formatter">


                  <span v-if="scope.row.isEdit&&column.isEdit&&!column.isSelect">

                    <el-input size="mini" placeholder="请输入内容" @click.stop.native="" v-model="scope.row[column.prop]">


                  <span v-else-if="scope.row.isEdit&&column.isEdit&&column.isSelect">

                    <el-select v-model="scope.row[column.prop]" placeholder="請輸入">

                        v-for="item in column.SelectObj"

                        :key="item.value"

                        :label="item.label"

                        :value="item.value">


                  <span v-else-if="scope.row.isEdit&&column.isEdit&&column.isDate">

                      v-model="scope.row[column.prop]"

                      type="datetime"

                      placeholder="Select date and time"

                      default-time="12:00:00">


                  <span v-else="!scope.row.isEdit" :style="column.style!=null||''?column.style:''" v-html="column.formatter(scope.row, column)">

                <template v-else>


                  <span v-if="scope.row.isEdit&&column.isEdit&&!column.isSelect&&!column.isDate">

                    <el-input size="mini" placeholder="请输入内容" @click.stop.native="" v-model="scope.row[column.prop]">


                  <span v-else-if="scope.row.isEdit&&column.isEdit&&column.isSelect">

                    <el-select v-model="scope.row[column.prop]" placeholder="請輸入">

                        v-for="item in column.SelectObj"

                        :key="item.value"

                        :label="item.label"

                        :value="item.value">


                  <span v-else-if="scope.row.isEdit&&column.isEdit&&column.isDate">

                      v-model="scope.row[column.prop]"

                      type="date"

                      placeholder="Pick a day"

                    >


                  <span v-else="!scope.row.isEdit" :style="column.style!=null||''?column.style:''">{{scope.row[column.prop]}}

              <template v-else>

                  :column="column"

                  :row="scope.row"

                  :render="column.render"

                  :index="index"

                >

        ref="fixedColumn"

        label="操作"

        align="center"

        :width="operates.width"

        :fixed="operates.fixed"

        v-if="operates.list.filter(_x=>_x.show=== true).length > 0"

      >

        <template slot-scope="scope">

          <div class="operate-group">

              v-if="!scope.row.isEdit"

              type="primary"

              size="mini"

              icon="el-icon-edit"

              plain

round

              @click.stop="EditButtonEvent(scope.$index, scope.row)">编辑

              v-if="!scope.row.isEdit"

              size="mini"

              type="danger"

              icon="el-icon-delete"

              plain

round

              @click.stop="DeleteButtonEvent(scope.$index, scope.row)">删除

              v-if="scope.row.isEdit"

              size="mini"

              type="info"

              icon="el-icon-refresh-right"

              plain

round

              @click.stop="CancelButtonEvent(scope.$index, scope.row)">取消

              v-if="scope.row.isEdit"

              size="mini"

              type="success"

              icon="el-icon-refresh"

              plain

round

              @click.stop="SaveButtonEvent(scope.$index, scope.row)">保存
































    <div class="pagination" v-show="pageShow">

        @size-change="handleSizeChange"

        @current-change="handleIndexChange"

        :page-size="pageSize"

        :page-sizes="[5,10,20,30,50,100]"

        :current-page="pageIndex"

        layout="total,sizes, prev, pager, next,jumper"

        :total="total"

      >


import MyColumnfrom "./MyColumn";

export default {

props: {

// 数据列表

    list: {

type: Array,

      default: []

},

    //表格高度

    height: {

type: Number,

      default:400

    },

    // 需要展示的列 === prop:列数据对应的属性,label:列名,align:对齐方式,width:列宽

    columns: {

type: [Array, Object],

      default: []

},

    // 总数

    total: {

type: Number,

      default:0

    },

    // 每页显示的数量

    pageSize: {

type: Number,

      default:10

    },

    // 操作按钮组 === label: 文本,type :类型(primary / success / warning / danger / info / text),

// show:是否显示,icon:按钮图标,plain:是否朴素按钮,disabled:是否禁用,method:回调方法

    operates: {},

    // table 表格的控制参数

    options: {

type: Object,

      default: {

// 是否为斑马纹 table

        stripe:false,

        // 是否要高亮当前行

        highlightCurrentRow:false

      }

},

    //需要合并的数据源

    mergeData:{

type: [Array,Object],

      default: ()=>({

data:[],//要合并的数据源

        columnIndex:[],//要合并的列的索引

        columnName:[],//要合并的列的名称

      }),

    },

    //需要表示状态行的标识

    rowSign:{

type:[Array,Object],

      default:()=>({

index:[],//比较字段在对象中的索引

        type:'',//判断是什么操作(状态值、正负值、区间值比)

        data:[],//需要比较的值、以及返回表格类样式

      })

},

    //是否需要分页部分

    pageShow:{

type:Boolean,

      default:true

    }

},

  //组件

  components: {

MyColumn,

    expandDom: {

functional:true,

      props: {

row: Object,

        render: Function,

        index: Number,

        column: {

type: Object,

          default:null

        },

      },

      render:(h, ctx) =>{

const params = {

row: ctx.props.row,

          index: ctx.props.index,

          size: ctx.props.size,

          round: ctx.props.round,

          circle: ctx.props.circle,

          plain: ctx.props.plain,

          show: ctx.props.show

        };

        if (ctx.props.column) params.column = ctx.props.column;

        //实现下拉框

        if(ctx.props.row.isEdit&&ctx.props.column.isSelect)

{

return h('el-select',{

props:{

value:ctx.props.row.state

            },

            on: {

'change':(event) => {

ctx.props.row.state=event;

              }

},

          },[ctx.props.column.SelectObj.map((val) => {// 下拉框里的内容,optionList下拉框数据

              return h('el-option', {

props: {

value: val.value,

                  label: val.label

                }

})

})

]);

        }

//实现输入框

        if(ctx.props.column.isEdit&&!ctx.props.column.isSelect)

{

debugger;

          return h('input',{

style:{

height:'28px !important',

              'border-radius':'4px !important',

              border:'1px solid #DCDFE6',

            },

            domProps: {

value:params.row.state

            },

            props:{

value:params.row.state

            },

            on: {

click(event){

event.stopPropagation();

              },

              input(event) {

params.row.state=event.target.value;

              }

}

})

}

return ctx.props.render(h, params);

      }

}

},

  // 数据

  data() {

return {

position:0,

      rowSpanArr: [],

      pageIndex:1,

      multipleSelection:[],

      rowInfo: [],//选中行数据

    };

  },

  created(){

this.getRowSpan();

  },

  mounted() {},

  computed: {},

  methods: {

//切换每页显示的条数

    handleSizeChange(size) {

this.pageIndex =1;

      this.$emit("handleSizeChange", size);

    },

    // 切换页码

    handleIndexChange(index) {

this.$emit("handleIndexChange", index);

      this.pageIndex = index;

    },

    // 多行选中

    handleSelectionChange(val) {

this.multipleSelection = val;

      this.$emit("handleSelectionChange", val);

    },

    //table行样式设置

    tableRowClassName({ row, rowIndex }) {

switch (this.rowSign.type) {

case 'state':

for(let i=0;i

{

if(Object.values(row)[this.rowSign.index]===this.rowSign.data[i].Id)

return this.rowSign.data[i].className;

          }

break;

        case 'bool':

if(Object.values(row)[this.rowSign.index[0]]>0)

return 'success-row';

          else if(Object.values(row)[this.rowSign.index[0]]<0)

return 'warning-row';

break;

        case 'section':

let num=Object.values(row)[this.rowSign.index[0]];

          for(let i=0;i

{

if(num>=this.rowSign.data[i].Number1&&num<=this.rowSign.data[i].Number2)

return this.rowSign.data[i].className;

          }

break;

        default:

break;

      }

return "";

    },

    //合并单元格

    objectSpanMethod({ row, column, rowIndex, columnIndex }) {

if(this.mergeData.columnIndex.length>0)

{

for(let i=0;i

{

if (columnIndex ===this.mergeData.columnIndex[i]) {

const _row =this.rowSpanArr['rowSpanArr'+i][rowIndex];

            const _col = _row >0 ?1 :0;

            return {

rowspan: _row,

              colspan: _col

}

}

}

}

},

    // 获取合并的数组

    getRowSpan() {

let that=this;

      this.rowSpanArr = {};

      let data_=that.mergeData.data;

      for(let i=0;i

{

let name=that.mergeData.columnName[i];

        that.mergeData.data.forEach((item, index) => {

if (index===0) {

that.rowSpanArr['rowSpanArr'+i] =[];

            that.rowSpanArr['rowSpanArr'+i].push(1);

            that.position =0;

          }else {

if (data_[index][name]===data_[index -1][name]) {

that.rowSpanArr['rowSpanArr'+i][that.position] +=1; //项目名称相同,合并到同一个数组中

              that.rowSpanArr['rowSpanArr'+i].push(0);

              data_[index][name] = data_[index -1][name];

            }else {

that.rowSpanArr['rowSpanArr'+i].push(1);

              that.position = index;

            }

}

});

      }

},

    //筛选方法

    filterchange(value) {

this.$emit("filterchange", value);

      return value;

    },

    //table单击事件

    rowclick(row, col, event) {

this.$emit("rowclick", row, col, event);

    },

    //双击事件

    dblclick(val) {

this.$emit("dblclick", val);

    },

    //右键事件

    contmenuclick(val) {

this.$emit("contmenuclick", val);

    },

    //单元格点击事件

    cellclick(row, col, cell, event) {

this.$emit("cellclick", row, col, cell, event);

    },

    rowClass({ row, rowIndex}){

return "background:rgba(236,240,245,0.4)";

    },

    headerStyle ({row, column, rowIndex, columnIndex}) {

if(row&&row[0].children)

{

return 'speHeader';

      }

},

    //编辑按钮事件

    EditButtonEvent(index,row)

{

this.$emit("EditButtonEvent", index, row);

    },

    //删除按钮事件

    DeleteButtonEvent(index,row)

{

this.$emit("DeleteButtonEvent", index, row);

    },

    //取消按钮事件

    CancelButtonEvent(index,row)

{

this.$emit("CancelButtonEvent", index, row);

    },

    //保存按钮事件

    SaveButtonEvent(index,row)

{

this.$emit("SaveButtonEvent", index, row);

    }

},

  watch:{

mergeData:{

handler(newVal,oldVal){

this.getRowSpan();

      },

      deep:true,

      immediate:true

    },

  }

};

.el-table .warning-row {

background:#fd9165;

}

.el-table .success-row {

background:#94f987;

}

.el-table .danger-row {

background:#f9400b;

}

.el-table .primary-row {

background:#abb7f9;

}

.speHeader{

color:blue

}

.el-input__inner{

height:28px !important;;

}

    :prop="col.prop"

    :label="col.label"

    :min-width="col.width"

    :fixed="col.fixed"

    align="center"

    :filters="col.filters"

  >

    <template slot-scope="scope">

      <template v-if="!col.render">

        <template v-if="col.formatter">

          <span v-if="scope.row.isEdit&&col.isEdit&&!col.isSelect">

            <el-input size="mini" placeholder="请输入内容" @click.stop.native="" v-model="scope.row[col.prop]">

          <span v-else-if="scope.row.isEdit&&col.isSelect">

            <el-select v-model="scope.row[col.prop]" placeholder="請輸入">

                v-for="item incol.SelectObj"

                :key="item.value"

                :label="item.label"

                :value="item.value">

          <span v-else="!scope.row.isEdit" :style="col.style!=null||''?col.style:''" v-html="col.formatter(scope.row,col)">

        <template v-else>

          <span v-if="scope.row.isEdit&&col.isEdit&&!col.isSelect">

            <el-input size="mini" placeholder="请输入内容" @click.stop.native="" v-model="scope.row[col.prop]">

          <span v-else-if="scope.row.isEdit&&col.isEdit&&col.isSelect">

            <el-select v-model="scope.row[col.prop]" placeholder="請輸入">

                v-for="item incol.SelectObj"

                :key="item.value"

                :label="item.label"

                :value="item.value">

          <span v-else="!scope.row.isEdit" :style="col.style!=null||''?col.style:''">{{scope.row[col.prop]}}

      <template v-else>

          :column="col"

          :row="scope.row"

          :render="col.render"

          :index="index">

    <template v-if="col.children">

        v-for="(item, index) incol.children"

        :key="index"

        :col="item"

      >

    export default {

name:"MyColumn",

      props: {

col: {

type: Object

}

},

      methods:{

myclass(){

return 'MyHeader'

        },

      }

}

<style scoped>

  .el-table thead tr:nth-child(1) {

color:blue !important;

  }

</style>