el-table 两种方法封装
main.js引入全局组件
问题:el-table-column只能放在el-table标签中,(多级表头时)单独封装会使表格列错位
解决:复杂表头需要加一列防止列错位,设置width为-1
一、第一种
1. 组件
<template>
<div>
<el-table :size="elTableSize" :data="tableData" :stripe="false" :border="columObj.border" :show-header="true" :highlight-current-row="true" @selection-change="handleSelectionChange" v-loading="columObj.loading" :row-class-name="tableRowClassName" @row-click="rowClick" :header-cell-style="$headerCellStyleFun" :cell-style="$cellStyleFun">
<!-- 选择框是否开启,selectable控制是否单行禁用 -->
<el-table-column v-if="columObj.selection" fixed type="selection" :selectable="columObj.selectable" width="50" />
<!-- 序号列是否开启 -->
<el-table-column v-if="columObj.showIndex" fixed type="index" label="序号" width="54" class-name="order_column" />
<!-- 普通列 -->
<!-- <el-table-column v-for="(column,columIndex) in columObj.columnData" :key="columIndex" :prop="column.prop" :label="column.label" :fixed="column.fixed" :width="column.width?column.width:column.multiLine?'300px':''" :sortable="column.sortable" :index="columIndex" :render-header="$renderHeaderFun"> -->
<el-table-column v-for="(column,columIndex) in columObj.columnData" :key="columIndex" :prop="column.prop" :label="column.label" :fixed="column.fixed" :width="column.width?column.width:column.multiLine?'300px':''" :sortable="column.sortable" :index="columIndex">
<template slot="header" slot-scope="scope">
<div class="table-head">{{ $rewriteHeader(scope) }}</div>
</template>
<template slot-scope="{row,$index}">
<!-- 默认展示 -->
<span v-if="column.text && column.editRow != $index">
<el-tooltip v-if="column.multiLine" :content="row[column.prop]" placement="top">
<p class="descStyle">{{row[column.prop]}}</p>
</el-tooltip>
<span v-else>{{row[column.prop]}}</span>
</span>
<!-- 自定义内容 -->
<span v-if="column.ownDefined">{{column.ownDefinedReturn(row,$index)}}</span>
<!-- tag -->
<div v-if="column.isTag">
<el-tag :size="elTableBtnSize" :type="column.getType(row,$index)">{{column.ownDefinedReturn(row,$index)}}</el-tag>
</div>
<!-- 状态对象展示 -->
<span v-if="column.status && row[column.prop]">{{row[column.prop].msg}}</span>
<!-- switch开关 -->
<el-switch v-if="column.switch" v-model="row[column.prop]" :inactive-text="row[column.prop] ? column.openText:column.closeText" @change="switchChange(row,$index,column.prop)" />
<!-- 图片展示 -->
<el-popover trigger="hover" placement="top" popper-class="popper">
<img v-if="column.image" :src=" row[column.prop]" />
<el-image slot="reference" v-if="column.image" :src="row[column.prop]" />
</el-popover>
<!-- 图片数组 -->
<el-popover v-if="column.imageArr" trigger="hover" placement="top" popper-class="popper">
<img v-if="row[column.prop].length>0" :src="row[column.prop][0]" />
<el-image slot="reference" v-if="row[column.prop].length >0" :src="row[column.prop][0]" :preview-src-list="row[column.prop]" />
</el-popover>
<!-- 可编辑input,仅在text默认展示类型才可编辑-->
<el-input v-focus v-if="column.editRow == $index" v-model="row[column.prop]" @blur="editInputBlur(row,$index,column.prop,columIndex)" />
<!-- 操作按钮 -->
<div v-if="column.isOperation">
<span v-for="(operations, index) in column.operation" :key="index">
<!-- <Buttons :size="elTableBtnSize" :type="operations.type" @parentClick="operations.buttonClick(row,$index)">
<span slot="title">{{operations.label}}</span>
</Buttons> -->
<el-button v-if="operations.isShow(row,$index)" :size="elTableBtnSize" :type="operations.type" @click="operations.buttonClick(row,$index)" :icon="operations.icon">{{operations.label}}</el-button>
</span>
</div>
</template>
</el-table-column>
<!-- 操作列 -->
<!-- <el-table-column v-for="(column,columIndex) in columObj.OperationList" :key="'c'+columIndex" :prop="column.prop" :label="column.label" :width="actionColWidth" class-name="operate-button" fixed="right" :sortable="column.sortable" :index="columIndex"> -->
<el-table-column v-for="(column,columIndex) in columObj.OperationList" :key="'c'+columIndex" :prop="column.prop" :label="column.label" :width="column.width" class-name="operate-button" fixed="right" :sortable="column.sortable" :index="columIndex">
<template slot="header" slot-scope="{column}">
<div class="table-head">{{ $rewriteOperateHeader(column) }}</div>
</template>
<template slot-scope="{row,$index}">
<!-- 操作按钮 -->
<span v-for="(operations, index) in column.operation" :key="index">
<!-- <Buttons :size="elTableBtnSize" :type="operations.type" @parentClick="operations.buttonClick(row,$index)">
<span slot="title">{{operations.label}}</span>
</Buttons> -->
<el-button v-if="operations.isShow(row,$index)" :size="elTableBtnSize" :type="operations.type" @click="operations.buttonClick(row,$index)" :icon="operations.icon">{{operations.label}}</el-button>
</span>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<!-- <div class="page_div" :style="{textAlign: pageObj.position || 'center'}">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :hide-on-single-page="false" :current-page="pageObj.pageData.page" :pager-count="7" :page-sizes="[10, 15, 20, 30,50]" :page-size="pageObj.pageData.size" background layout="total,sizes,prev, pager, next" :total="pageObj.total">
</el-pagination>
</div> -->
</div>
</template>
<script>
export default {
name: "index",
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
// }
},
data() {
// let readUploadFileUrl = this.$store.state.user.readUploadFileUrl;
return {
selectVal: []
// viewUrl: readUploadFileUrl,
}
},
mounted() {
this.$nextTick(() => {
// this.getTableColumnWidth()
})
},
methods: {
// 复选框选中的数据
handleSelectionChange(val) {
this.selectVal = val
},
// switchChange调用
switchChange(row, $index, prop) {
this.$emit("switchChange", row, $index, prop);
},
// 帮助点击行,获取点击的下标
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);
},
// 条数变化
handleSizeChange(e) {
this.$emit('handleSizeChange', e);
},
// 页码变化
handleCurrentChange(e) {
this.$emit('handleCurrentChange', e);
}
},
computed: {},
}
</script>
<style lang="scss" scoped>
.el-button {
margin: 0 6px;
}
::v-deep .el-input__inner {
border: none;
}
::v-deep .el-image__inner {
height: 50px;
}
// switch左边文字颜色
::v-deep .el-switch__label--left {
color: #606266;
}
img {
height: 400px;
}
.page_div {
padding: 15px 0;
}
</style>
2. 调用
<elTables ref="elTables" :tableData="tableList" :columObj="columObj"> </elTables>
data() {
return {
// 表格
tableList: [],
columObj: {
border: true,
loading: false,
// 选择框
selection: true,
// 序号列
showIndex: true,
// 选择框根据条件是否可选
selectable: (row, index) => {
if (row.switchs) {
return true;
}
},
lazy: "true",
//column列,columType(列类型,可选text(默认为普通文字模式),input(input可编辑框),switch(switch开关),image(图片),operation(操作按钮))
//prop(参数),label(列名),width(宽度),align(对齐方式),sortable(是否支持排序)
columnData: [
{
text: true,
prop: "name",
label: "姓名",
width: "100px",
fixed: true,
},
{
ownDefined: true,
prop: "sex",
label: "性别",
width: "80px",
ownDefinedReturn: (row, $index) => {
return this.getResult(row.sex, this.dataJSON.sex, $index)
}
},
],
// 操作列
//如果为操作列,则需要填写需要的操作按钮,类型为Object。operation(操作类型,可选edit,delete,see),type(按钮样式,参考el—botton类型),label(按钮文字)icon(参考el-icon),color(字体颜色)
isOperation: true,
OperationList: [
{
label: "操作",
width: "280",
fixed: "right",
align: "center",
sortable: false,
operation: [
{
type: "primary",
label: "编辑",
buttonClick: this.showEditPopup, // 点击编辑按钮
isShow: (row, $index) => {
return true;
}
},
]
},
]
},
}
},
// 根据返回数据匹配字典数据
getResult(rowVal, zidian, $index) {
let result
zidian.forEach(item => {
if (rowVal !== "" && item.value == rowVal) {
result = item.name
}
});
return result
},
二、第二种 - 使用插槽
1. 组件
cusTable.vue
<template>
<div class="el-table">
<el-table class="my-table" ref="table" :data="listData" border style="width: 100%" @selection-change="handleSelectionChange">
<!-- 是否需要选择器 -->
<el-table-column fixed v-if="showSelectColumn" type="selection" align="center" width="60"></el-table-column>
<!-- 是否需要序号 -->
<el-table-column fixed v-if="showIndexColumn" type="index" align="center" width="60"></el-table-column>
<!-- <template> -->
<!-- <elCol :propList="propList"></elCol> -->
<el-table-column v-for="propItem in propList" :key="propItem.prop" v-bind="propItem" align="center">
<!-- 复杂表头时使用elCol组件 -->
<template v-if="propItem.fzCol">
<!-- 多级表头时使用elCol组件 -->
<elCol :propList="propItem.colList"></elCol>
<!-- 二级表头可以使用一下代码 -->
<!-- <el-table-column v-for="item in propItem.colList" :key="item.prop" v-bind="item" align="center">
<template #default="scope">
<slot :name="item.slotName" :row="scope.row">
{{ scope.row[item.prop] }}
</slot>
</template>
</el-table-column> -->
</template>
<!-- 一行表头,简单表格 -->
<template v-if="!propItem.fzCol" #default="scope">
<!-- 为表格预留插槽 -->
<slot :name="propItem.slotName" :row="scope.row">
{{ scope.row[propItem.prop] }}
</slot>
</template>
</el-table-column>
<!-- </template> -->
</el-table>
</div>
</template>
<script>
export default {
name: "cus-table",
props: {
listData: {
type: Array,
required: true
},
propList: {
type: Array,
required: true
},
showSelectColumn: {
type: Boolean,
required: false
},
showIndexColumn: {
type: Boolean,
required: false
},
},
data() {
return {};
},
mounted() {
this.$nextTick(() => {
this.$refs.table.doLayout()
})
},
methods: {
handleSelectionChange(value) {
this.$emit('selectionChange', value)
}
},
};
</script>
elCol.vue
<template>
<!-- 复杂表头 -->
<div>
<!-- 复杂表头加一列防止列错位,设置width为-1 -->
<el-table-column class="my-column" width="-1" ></el-table-column>
<el-table-column v-for="(propItem,index) in propList" :key="index" v-bind="propItem" align="center">
<template v-if="propItem.fzCol">
<!-- 调用本身(elCol组件) -->
<elCol :propList="propItem.colList"></elCol>
</template>
<template v-if="!propItem.fzCol" #default="scope">
<slot :name="propItem.slotName" :row="scope.row" :index="scope.$index">
{{ scope.row[propItem.prop] }}
</slot>
</template>
</el-table-column>
</div>
</template>
<script>
export default {
name: "elCol",
props: {
propList: {
type: Array,
required: true
},
},
};
</script>
2. 调用
<template>
<div class="content">
<cusTable :listData="userList" :propList="propList" :showSelectColumn="true" :showIndexColumn="true" @selectionChange="selectionChange">
<!-- 传入插槽,插槽支持多个 -->
<!-- 第一种 -->
<template #sex="{ row }">
<span>{{ row.sex === '1' ? '男' : '女' }}</span>
</template>
<template #status="scope">
<el-button type="text">{{ scope.row.status === '1' ? '是' : '否' }}</el-button>
</template>
<!-- 第二种 -->
<template slot="sex" slot-scope="{ row }">
<span>{{ row.sex === '1' ? '男' : '女' }}</span>
</template>
<template slot="status" slot-scope="scope">
<span>{{ scope.row.status === '1' ? '是' : '否' }}</span>
</template>
<template #handler>
<div class="handle-btns">
<el-button icon="el-icon-edit" size="mini" type="text">编辑</el-button>
<el-button icon="el-icon-delete" size="mini" type="text">删除</el-button>
</div>
</template>
</cusTable>
</div>
</template>
<script>
import cusTable from '../unit/table.vue'
export default {
name: "index2",
components: {
cusTable
},
data() {
return {
userList: [],
propList: [
{ prop: 'name', label: '用户名', width: '100' },
{ prop: 'cellphone', label: '手机号码', minWidth: '100' },
// slotName 需要自定义数据的插槽名
{ prop: 'sex', label: '性别', minWidth: '100', slotName: 'sex' },
{ prop: 'status', label: '是否', minWidth: '100', slotName: 'status' },
// fzCol 复杂表头
{
label: '地址',
minWidth: '250',
fzCol: true,
colList: [
{
label: '市/区', minWidth: '100',
fzCol: true,
colList: [
{ prop: 'city', label: '市', minWidth: '100' },
{ prop: 'qu', label: '区', minWidth: '100' },
]
},
{ prop: 'cun', label: '村', minWidth: '100' },
]
},
{
prop: 'createAt',
label: '创建时间',
minWidth: '250',
},
{ label: '操作', minWidth: '120', slotName: 'handler' }
]
};
},
created() {
// 异步操作后给表格赋值
this.userList = [
{
name: '张三',
cellphone: '188888888888',
sex: '1',
status: '1',
createAt: '2023-4-17',
city: 'A市',
qu: 'A区',
cun: 'A村',
},
{
name: '李四',
cellphone: '188888888888',
sex: '1',
status: '0',
createAt: '2023-4-17',
city: 'B市',
qu: 'B区',
cun: 'B村',
}
]
},
mounted() { },
methods: {
selectionChange(val) {
console.log(val)
}
},
};
</script>