記錄一下在對el-tabel進行簡單封裝并實現行內編輯,單元格合并等功能
? ? <el-table
? ? ? id="iTable"
? ? ? v-loading.iTable="options.loading"http://是否添加表格loading加載動畫
? ? ? :data="list"http://數據列
? ? ? :stripe="options.stripe"http:// 是否添加表格loading加載動畫
? ? ? ref="multipleTable"http:// 是否支持列表項選中功能
? ? ? border
? ? ? :default-sort="{order: 'descending'}"
? ? ? @selection-change="handleSelectionChange"
? ? ? @filter-change="filterchange"
? ? ? :header-cell-style="rowClass"http://多級表頭控制樣式
? ? ? :header-cell-class-name="headerStyle"http://表頭樣式
? ? ? :row-class-name="tableRowClassName"http://行樣式
? ? ? :span-method="objectSpanMethod"http://合并單元格
? ? ? :height="height"http://高度
? ? ? size="small"
? ? ? :row-style="{height:'30px'}"
? ? ? :cell-style="{padding:'0px'}"
? ? ? @row-click="rowclick"http://行點擊事件
? ? ? @row-dblclick="dblclick"http://雙擊
? ? ? @row-contextmenu="contmenuclick"http://右鍵
? ? ? @cell-click="cellclick"http://單元格事件
? ? >
? ? ? <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>