内容背景
公司开发的管理后台系统需要用到大量的表格数据,每个页面内容大致相同,为了便于后期维护,便考虑将el-table进行封装,将公共部分内容提取出来,后期只需对表格内容进行维护即可。
使用到的技术:
- vue
- Element-ui
封装内容
简单来说,就是把el-table中的属性数据显示都是用父组件传进来,都可以自定义。
官方的el-table组件
-
表格属性:
项目常用属性:data,显示表格数据;
height:定义table表格的高度。
stripe: 表格为斑马纹。
filter-multiple:数据过滤的选项是否多选。
-
表格方法:
row-class-name:行的className回调方法,用来给指定行进行颜色高亮区分。
sort-change: 当表格的排序条件发生变化的时候会触发该事件。
filter-change: 表格筛选条件发生变化的时候会触发该事件。
封装表格
<el-table
ref="filterTable"
:row-class-name="tableRowClassName"
border
v-loading="loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
:data="tableData"
:height="height || undefined"
:max-height="height || undefined"
:cell-style="cellStyle"
:default-sort = "{prop: 'id', order: null}"
@sort-change="sortChange"
@filter-change="handleFilterChange"
style="width: 100%">
<template v-for="(item, index) in columns">
<el-table-column
:show-overflow-tooltip="true"
v-if="item.show != false"
:key="index"
:sortable="item.sortable"
:prop="item.prop"
:label="item.label"
:align="item.align ? item.align : 'left'"
:width="item.width"></el-table-column>
<template v-for="(filter, index) in item.filterColums">
<!-- 表格内联下拉框样式-->
<el-table-column
v-if="filter.type == 'select' && filter.show != false"
:label="columnLabel[index]"
:key="filter.lable"
:prop="filter.prop"
:show-overflow-tooltip="true"
:fixed="filter.fixed ? filter.fixed : false"
:width="filter.width ? filter.width : ''"
:filter-multiple="multiple"
:filters="filter.filtersList"
:filter-method="filterMethod"
:column-key="filter.prop">
<template slot-scope="props">
<el-select
class="select-row"
v-if="filter.part == 'sell'"
v-model="props.row.sell_id"
placeholder="请选择"
@change="filterChange(props.row)"
style="height: 25px;">
<el-option
v-for="filter in filtersList"
:key="filter.id"
:label="filter.realname"
:value="filter.id"
></el-option>
</el-select>
</template>
</el-table-column>
<!-- solt 自定义列-->
<template v-if="item.type === 'slot'">
<el-table-column
:key="index"
:width="item.width"
:prop="item.prop"
:label="item.label">
<template slot-scope="scope">
<slot :name="item.slotType" :row="scope.row" />
</template>
</el-table-column>
</template>
</template>
<!-- 表格操作按钮-->
<el-table-column
v-if="tableOption && tableOption.label"
:width="tableOption.width"
:label="tableOption.label"
fixed="right"
align="center"
class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
v-for="(item,index) in tableOption.options"
:key="index"
:type="item.type"
:icon="item.icon"
v-show="!scope.row.validStatus"
@click="handleButton(item.methods,scope.row)"
size="mini">
{{item.label}}
</el-button>
</template>
</el-table-column>
</el-table>
我的项目中有几处需要用到表格内下拉框的情况,所以在这里进行了一个type == 'select'的区别封装,通常使用自定义列即可满足需求,具体情况可按照自己项目进行调整
接下来就是将table中的数据内容暴露出来,供父组件传递数据。如下:
props: {
tableData: Array,
tableOption: Object,
filterColums: Array,
columns: Array,
tableRowClassName: Function,
loading: Boolean,
filtersList: Array,
filtersRoleList: Array,
columnLabel: Array,
filterMethod: Function,
cellStyle: Function,
refTable: String,
multiple: {
type: Boolean,
default: false
},
// 监听高度
listenHeight: {
type: Boolean,
default: true
}
},
数据暴露出来之后,再将方法暴露给父组件,如下:
methods: {
handleButton(methods, row, event) {
this.$emit('handleButton',{ 'methods':methods,'row':row })
},
filterChange (row) {
this.$emit('filterChange', row)
},
filterRoleChange (row) {
this.$emit('filterRoleChange', row)
},
handleFilterChange (filters) {
this.$emit('handleFilterChange', filters)
},
sortChange (filters) {
this.$emit('sortChange', filters)
},
switchChange (row) {
this.$emit('switchChange', row)
},
rowClick (type, value) {
this.$emit('rowClick', type, value)
},
}
以上,表格已经封装完毕,接下来我们开始在项目中使用他吧~
页面使用
<Table
:loading="loading"
:tableData="tableData"
:table-option="tableOption"
:columns="tableColumns"
:columnLabel="softwareLable"
:filtersList="softwareFiltersList"
:cellStyle="cellStyle"
@handleFilterChange="handleFilterChange"
@handleButton="handleButton">
<template #enable="scope">
<el-switch
active-color="#239656"
inactive-color="#e86161"
v-model="scope.row.enable"
@change="changeSwitch(scope.row, 'enable')">
</el-switch>
</template>
</Table>
// tableColumns.js
export const tableColumns = [
{ prop: 'id', label: 'ID', width: 70 },
{ prop: 'name', label: '名称' },
{ prop: 'description', label: '描述'},
{
show: false,
filterColums:[
{
prop: 'software_name',
label: '适用软件',
type: "text",
filtersList: [
{
text: '软件1',
value: 1
},
{
text: '软件2',
value: 2
},
{
text: '软件3',
value: 3
},
{
text: '软件4',
value: 4
},
{
text: '软件5',
value: 5
}
]
},
]
},
{ prop: 'price', label: '单价'},
{ prop: 'price_range', label: '价格范围'},
{ prop: 'scale', label: '系数'},
{ show: false, prop: 'enable', label: '可用', type: 'slot', slotType: 'enable'},
]
export const tableOption = {
label: '操作',
width: '120',
options: [
{ label: '', type: 'text', icon: 'el-icon-edit-outline', methods: 'edit' },
{ label: '', type: 'text', icon: 'el-icon-delete', methods: 'delete' },
]
}
<script>
import Table from '@/components/myTable/index'
import { tableColumns, tableOption } from './tableColumns'
export default {
components: {
Table
},
data() {
return {
loading: false,
tableData: [],
tableOption: tableOption,
tableColumns: tableColumns,
softwareLable: ['软件'],
softwareFiltersList: [],
}
},
methods: {
getTableData () {
// 接口数据信息获取
},
cellStyle () {
// 表格行内样式
},
handleFilterChange () {
// 表格筛选方法
},
handleButton () {
// 表格操作方法
},
changeSwitch () {
// Switch 操作方法
}
},
}
</script>
以上,完整的项目就可以呈现。对应的一些方法操作可自行添加。 封装不够完美,有什么好的方法欢迎大家一起讨论~