组件效果
![](https://img-blog.csdnimg.cn/direct/636b05be61f142009c3e82c2a78e8d29.png)
1.el-table组件封装代码
<template>
<div class="godtable">
<div class="god_table_mian">
<el-table
ref="tableDataRef"
v-loading="loading"
:data="dataSource"
:stripe="stripe"
:border="border"
:size="size"
:highlight-current-row="highlightCurrentRow"
:row-key="rowKey"
:empty-text="emptyText"
:lazy="lazy"
:default-expand-all="expandAll"
:tree-props="treeProps"
@select="onSelect"
@select-all="onSelectAll"
@selection-change="onSelectionChange"
@cell-mouse-enter="onCellMouseEnter"
@cell-mouse-leave="onCellMouseLeave"
@cell-click="onCellClick"
@cell-dblclick="onCellDblclick"
@row-click="onRowClick"
@row-contextmenu="onRowContextmenu"
@row-dblclick="onRowDblclick"
@header-click="onHeaderClick"
@header-contextmenu="onHeaderContextmenu"
@sort-change="onSortChange"
@filter-change="onFilterChange"
@current-change="onCurrentChange"
@header-dragend="onHeaderDragend"
@expand-change="onExpandChange"
>
<template v-for="(col, index) in insideColumns">
<!-- 操作列/自定义列 -->
<slot v-if="col.slot" :name="col.prop" />
<!-- 普通列 -->
<el-table-column
v-else
:key="index"
:prop="col.prop"
:label="col.label"
:width="col.width"
:formatter="col.formatter"
:type="col.type"
:index="col.index"
:column-key="col.columnKey"
:min-width="col.minWidth"
:fixed="col.fixed"
:render-header="col.renderHeader"
:sortable="col.sortable"
:sort-method="col.sortMethod"
:sort-by="col.sortBy"
:sort-orders="col.sortOrders"
:resizable="col.resizable"
:show-overflow-tooltip="col.showOverflowTooltip"
:align="col.align"
:header-align="col.headerAlign"
:class-name="col.className"
:label-class-name="col.labelClassName"
:selectable="col.selectable"
:reserve-selection="col.reserveSelection"
:filters="col.filters"
:filter-placement="col.filterPlacement"
:filter-multiple="col.filterMultiple"
:filtered-value="col.filteredValue"
>
<template slot-scope="scope">
<GodSlot
v-if="col.render"
:column="col"
:row="scope.row"
:render="col.render"
:index="index"
/>
<span v-else>{{ scope.row[col.prop] }}</span>
</template>
</el-table-column>
</template>
</el-table>
</div>
<div v-if="pagination" :class="fixed ? 'fixed' :'pagination'">
<el-pagination
background
:page-sizes="[5, 10, 20, 30, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="dataTotal"
:current-page="currentPage"
@size-change="onsizeChange"
@current-change="currentChange"
/>
</div>
</div>
</template>
<script>
/**
* @GodSlot 自定义插槽组件
*
*/
const GodSlot = {
functional: true,
props: {
row: Object,
render: Function,
index: Number,
column: {
type: Object,
default: null
}
},
render: (h, data) => {
const params = {
row: data.props.row,
index: data.props.index
}
if (data.props.column) params.column = data.props.column
return data.props.render(h, params)
}
}
export default {
name: 'GodTable',
components: { GodSlot },
props: {
pagination: {
type: Boolean,
default: true
},
/**
* @see dataTotal
* */
dataTotal: {
type: Number,
default: 0
},
/**
* @see currentPage
* */
currentPage: {
type: Number,
default: 0
},
/**
* @see pageSize
* */
pageSize: {
type: Number,
default: 0
},
/**
* @see loading 是否显示加载中
*/
loading: {
type: Boolean,
default: false
},
/**
* @see dataSource 数据集合
*/
dataSource: {
type: Array,
default() {
return []
}
},
/**
* @see stripe 是否为斑马边框
* */
stripe: {
type: Boolean,
default: false
},
/**
* @see border 是否带有纵向边框
*/
border: {
type: Boolean,
default: true
},
/**
* @see Table 的尺寸
* */
size: {
type: String,
default: 'medium' // medium / small / mini
},
fixed: {
type: Boolean,
default: true
},
/**
* @see highlightCurrentRow 是否要高亮当前行
* */
highlightCurrentRow: {
type: Boolean,
default: false
},
/**
* @see emptyText 空数据时显示的文本内容,也可以通过 slot="empty" 设置
* */
emptyText: {
type: String,
default: ''
},
/**
* @see expandAll 是否默认展开所有行,当 Table 包含展开行存在或者为树形表格时有效
* */
expandAll: {
type: Boolean,
default: false
},
/**
* @see treeProps 渲染嵌套数据的配置选项
* */
treeProps: {
type: Object,
default() {
return {}
}
},
/**
* @see lazy 是否懒加载子节点数据
* */
lazy: {
type: Boolean
},
// eslint-disable-next-line vue/require-default-prop
rowKey: {
type: [Function, String]
},
indent: {
type: Number,
default: 16
},
headerShow: {
type: Boolean,
default: true
},
columns: {
type: Array,
default() {
return []
}
}
},
data() {
return {
insideColumns: [],
loadingTb: false,
tableData: [],
pageSizeTb: 10,
pageTb: 1,
totalTb: 0
}
},
watch: {
pageSize: {
handler(newV) {
},
deep: true,
immediate: true
}
// (newV) {
// }
},
created() {
this.tableColumns()
},
methods: {
tableColumns() {
const columns = this.columns
this.insideColumns = []
columns.forEach((col) => {
// 默认居中
if (!col.align) {
col.align = 'center'
}
// 默认显示文字提示
if (!col.showOverflowTooltip) {
col.showOverflowTooltip = true
}
this.insideColumns.push(col)
})
// 表格错位
this.$nextTick(() => {
this.$refs.tableDataRef.doLayout()
})
},
/**
* @function onSelect 当用户手动勾选数据行的 Checkbox 时触发的事件
* */
onSelect(selection, row) {
this.$emit('select', selection, row)
},
/**
* @function onSelectAll 当用户手动勾选全选 Checkbox 时触发的事件
* */
onSelectAll(selection) {
this.$emit('select-all', selection)
},
/**
* @function onSelectionChange 当选择项发生变化时会触发该事件
* */
onSelectionChange(selection) {
this.$emit('selection-change', selection)
},
/**
* @function onCellMouseEnter 当单元格 hover 进入时会触发该事件
* */
onCellMouseEnter(row, column, cell, event) {
this.$emit('cell-mouse-enter', row, column, cell, event)
},
/**
* @function onCellMouseLeave 当单元格 hover 退出时会触发该事件
**/
onCellMouseLeave(row, column, cell, event) {
this.$emit('cell-mouse-leave', row, column, cell, event)
},
/**
* @function onCellClick 当某个单元格被点击时会触发该事件
* */
onCellClick(row, column, cell, event) {
this.$emit('cell-click', row, column, cell, event)
},
/**
* @function onCellDblclick 当某个单元格被双击击时会触发该事件
* */
onCellDblclick(row, column, cell, event) {
this.$emit('cell-dblclick', row, column, cell, event)
},
/**
* @function onRowClick 当某一行被点击时会触发该事件
* */
onRowClick(row, column, event) {
this.$emit('row-click', row, column, event)
},
/**
* @function onRowContextmenu 当某一行被鼠标右键点击时会触发该事件
* */
onRowContextmenu(row, column, event) {
this.$emit('row-contextmenu', row, column, event)
},
/**
* @function onRowDblclick 当某一行被双击时会触发该事件
* */
onRowDblclick(row, column, event) {
this.$emit('row-dblclick', row, column, event)
},
/**
* @function onHeaderClick 当某一列的表头被点击时会触发该事件
* */
onHeaderClick(column, event) {
this.$emit('header-click', column, event)
},
/**
* @function onHeaderContextmenu 当某一列的表头被鼠标右键点击时触发该事件
* */
onHeaderContextmenu(column, event) {
this.$emit('header-contextmenu', column, event)
},
/**
* @function onSortChange 当表格的排序条件发生变化的时候会触发该事件
* */
onSortChange({ column, prop, order }) {
this.$emit('sort-change', { column, prop, order })
},
/**
* @function onFilterChange 当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。
* */
onFilterChange(filters) {
this.$emit('filter-change', filters)
},
/**
* @function onCurrentChange 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性
* */
onCurrentChange(currentRow, oldCurrentRow) {
this.$emit('current-change', currentRow, oldCurrentRow)
},
/**
* @function onHeaderDragend 当拖动表头改变了列的宽度的时候会触发该事件
* */
onHeaderDragend(newWidth, oldWidth, column, event) {
this.$emit('header-dragend', newWidth, oldWidth, column, event)
},
/**
* @function onExpandChange 当用户对某一行展开或者关闭的时候会触发该事件(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded)
* */
onExpandChange(row, expand) {
this.$emit('expand-change', row, expand)
},
/**
* @function onsizeChange 设置页大小
* */
onsizeChange(pageSize) {
this.$emit('feat-params', { pageSize })
},
/**
* @function currentChange 监听当前页
* */
currentChange(current) {
this.$emit('feat-params', { currentPage: current })
}
}
}
</script>
<style lang="scss">
.godtable {
position: relative;
.god_table_mian {
margin-bottom: 100px;
}
.pagination {
text-align: right;
width: 100%;
}
.fixed {
text-align: right;
position: fixed;
bottom: 0;
right: 0;
z-index: 999;
background: #fff;
margin-top: 10px;
overflow: hidden;
padding: 10px 20px;
width: 100%;
}
}
</style>
2.父组件调用例子
<template>
<div class="app-container">
<GodTable
:columns="columns"
:height="'700px'"
:loading="loading"
:data-source="dataSource"
:data-total="dataTotal"
:page-size="param.pageSize"
@feat-params="getparams"
>
<el-table-column slot="index" type="index" label="序号" width="50" />
<el-table-column slot="operation" type="index" label="操作" width="80" align="center">
<template slot-scope="scope">
<el-link
size="mini"
type="danger"
@click="details(scope.row)"
>查看详情</el-link>
</template>
</el-table-column>
</GodTable>
</div>
</template>
<script>
import GodTable from '@/components/GodTable'
import { getPage } from '@/api/protectMana'
export default {
components: {
GodTable
},
data() {
return {
dataSource: [],
dataTotal: 0,
param: {
pageSize: 20,
currentPage: 1,
keyword: ''
},
columns: [
{
slot: 'index',
prop: 'index'
},
{
label: '昵称',
prop: 'nickname'
},
{
label: '创建时间',
prop: 'createSystemTime'
},
{
slot: 'operation',
prop: 'operation'
}
]
}
},
async created() {
this.getdataSource()
},
methods: {
/**
* @function getparams 接收参数
* */
getparams(params) {
this.param = {
...this.param,
...params
}
this.getdataSource()
},
reset() {
this.param = {
pageSize: 20,
currentPage: 1
}
this.getdataSource()
},
/**
* @function getdataSource 获取页面接口数据
* */
async getdataSource() {
const res = await getPage(this.param)
if (res.code === 200) {
this.dataSource === res.data
}
},
details(row) {
console.log(row)
}
}
}
</script>
<style lang="scss" scoped>
</style>