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>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266