vue2 el-table 封装
- 在 custom 文件夹下面创建 tableList.vue
- 直接上代码(代码比较多,复制可直接用)
javascript
<template>
<div class="mp-list">
<el-table
ref="multipleTable"
class="mp-custom-table"
:data="tableData"
v-loading="fullLoading"
:highlight-current-row="highlightCurrentRow"
:row-class-name="rowClassName"
:border="isBorder"
:reserve-selection="false"
@row-click="handleClickRow"
@current-change="handleCurrentChange"
:row-key="rowKey"
:default-expand-all="defaultExpandAll"
:expand-row-keys="expandRowKeys"
@expand-change="expandChangeClick"
@header-click="handleClickHeader"
doLayout
:stripe="true"
:default-sort="defaultSort"
@selection-change="handleSelectionChange"
@filter-change="filterChangeFn"
@row-dblclick="ondblclick"
width="100%"
:height="tableHeight"
:max-height="maxHeight"
@select="select"
@select-all="selectAll"
:header-cell-style="headerCellStyle"
@cell-mouse-enter="cellMouseEnter"
@cell-mouse-leave="cellMouseLeave"
@sort-change="sortChange"
:key="statusKey"
>
<el-table-column v-if="selecShow" :align="selecShowAlign" :selectable="selectable" type="selection" width="60"></el-table-column>
<el-table-column v-if="needSerialNumber" type="index" :label="serialNumberName"></el-table-column>
// 行详情插槽
<template v-if="expand">
<slot name="expand"></slot>
</template>
<!-- theadData 配置项加了showOverTip字段,控制当前列是否使用tooltip,不传默认原来true -->
<template v-for="(item, idx) of theadData">
<el-table-column
:label="item.title"
:width="item.width"
:prop="item.field"
:sortable="item.sortable"
:key="`${item.field || item.prop}_${idx}`"
:min-width="item.minWidth"
:align="cellAlign"
:class-name="item.highlight ? 'mp-highlight' : ''"
:sort-by="item.sortBy"
:filter-placement="'bottom'"
:filters="item.filters"
:filter-method="item.filterMethod"
:filter-multiple="false"
:columnKey="item.field"
:sort-method="item.sortFn"
:show-overflow-tooltip="item.showOverTip !== undefined ? item.showOverTip : true"
>
<!-- 给列表的th添加提示icon,鼠标进过后显示tooltip,配置theadData时,配置headerTip内容,则展示到此,未配置不展示icon -->
<template slot="header" v-if="item.headerTip">
<span>
{{ item.title }}
<el-tooltip effect="dark" placement="top" :content="item.headerTip">
<i class="el-icon-info"></i>
</el-tooltip>
</span>
</template>
<template slot-scope="scope">
<slot v-if="item.isSlot" :name="item.field" :scope="scope" :row="scope.row" :column="scope.column" :store="scope.store" :_self="scope._self"></slot>
<div v-else>
<div v-if="item.htmlCustom && typeof item.htmlCustom === 'function'" v-html="item.htmlCustom(scope.row, scope.column, scope.row[item.field], item.field) || '--'"></div>
<span v-else>{{ fieldDeel(scope.row, item.field) || '--' }}</span>
</div>
</template>
</el-table-column>
</template>
<template slot="empty">
<div class="mp_tatble_nodata">
// 表格数据为空时,显示暂无数据图片
// 图片根据自己的主题,更换合适的图片
<img class="mp_noData_image" src='/img/dark_no_data.png' alt />
<p class="mp_tatble_txt">暂无数据</p>
</div>
</template>
<slot name="slotTip"></slot>
<slot name="operbtn"></slot>
<!-- other 是为了处理表格列key在某个子对象下,父组件正常循环 -->
<slot name="other"></slot>
</el-table>
</div>
</template>
<script>
export default {
name: 'tableList',
props: {
//表格高亮当前选中行
highlightCurrentRow: {
default: false,
},
expand: {
type: Boolean,
default: false,
},
rowKey: {
type: String,
default: 'id',
},
expandRowKeys: {
type: Array,
default: () => [],
},
// table高度,接收String
tableHeight: {
default: false,
},
maxHeight: {
type: String,
default: '100%',
},
tableData: Array, // 表格内容
theadData: {
type: Array,
}, // 表头内容
fullLoading: Boolean, // 加载遮罩
sid: String,
selecShow: {
// 是否有选择框
type: Boolean,
default: false,
},
selecShowAlign: {
type: String,
default: 'left'
},
isBorder: {
type: Boolean,
default: true,
},
bk_obj_name: '',
cellAlign: {
type: String,
default: 'left',
},
//设置表头样式
headerCellStyle: {
type: Object,
},
serialNumberName: {
type: String,
default: '序号',
},
needSerialNumber: {
type: Boolean,
default: false,
},
defaultExpandAll: {
type: Boolean,
default: false,
},
// 默认排序
defaultSort: {
type: Object,
default: {
prop: 'date',
},
},
rowClassName: {
type: Function,
},
},
data() {
return {
idSelection: [],
statusKey: 0,
}
},
created() {},
methods: {
fieldDeel(row, field) {
let arr = field.split('.')
let text = row
arr.forEach((item) => {
text = text[item]
})
if (text == 0) {
text = text + ''
}
return text
},
handleClickHeader(col, e) {
// 点击某一表头
if (col && col.sortable) {
}
},
filterChangeFn(filter) {
if (typeof this.$parent.getFilterValueFn === 'function') {
this.$parent.getFilterValueFn(filter)
}
},
handleClickRow(row, col, e) {
//点击某一行跳转
if (col && col.className) {
if (col.className == 'mp-highlight') {
this.$emit('handleClickRow', row, col, this.bk_obj_name)
}
}
},
ondblclick(row, col, e) {
// 某一行的双击事件
this.$emit('ondblclick', row, col)
},
toggleSelection(rows, selected) {
this.$nextTick(() => {
if (rows) {
rows.forEach((row) => {
this.$refs.multipleTable.toggleRowSelection(row, selected)
})
} else {
this.$refs.multipleTable.clearSelection()
}
})
},
// 单行设置高亮
setCurrentRowHandel(row) {
this.$nextTick(() => {
this.$refs.multipleTable.setCurrentRow(row[0])
})
},
refreshLayout() {
this.$nextTick(() => {
this.$refs.multipleTable.doLayout()
})
},
// 展开航
expandChangeClick(row, expandRow) {
this.$emit('expandChange', row, expandRow)
},
handleSelectionChange(val) {
// 多选
this.idSelection = []
val.forEach((item) => {
this.idSelection.push(item[this.sid])
})
this.$emit('changeData', this.idSelection, val)
this.$emit('queryRow', val)
},
selectable(row, index) {
// 是否禁用多选
let state = true
if (row.typeFlagOrganization) {
state = !row.typeFlagOrganization
}
return state
},
// 手动勾选数据行的 Checkbox 时触发的事件
select(selection, row) {
this.$emit('select', selection, row)
},
selectAll(selection) {
this.$emit('select-all', selection)
},
cellMouseEnter(row, column, cell, event) {
this.$emit('cell-mouse-enter', { row, column, cell, event })
},
cellMouseLeave(row, column, cell, event) {
this.$emit('cell-mouse-leave', { row, column, cell, event })
},
// 点击表格行时选中
handleCurrentChange(row) {
// this.$refs.multipleTable.toggleRowSelection(row)
if (this.highlightCurrentRow) {
//有高亮效果可单选 ---平面图资产关联使用
this.$emit('handleCurrentChange', row)
}
},
formatterCellval(row, column, cellValue, index) {
// 没有内容时的占位符,暂时无用
if (typeof this.$parent.customFormatterCellval === 'function') {
// 判断外部是否有customFormatterCellval方法
const value = this.$parent.customFormatterCellval(row, column, cellValue, index)
return value
} else {
// 没有-赋值给表格
if (!Boolean(cellValue)) {
return '--'
} else {
return cellValue
}
}
},
// 排序方法
sortFn(a, b) {},
// 监听排序事件
sortChange(data) {
this.$emit('sort-change', data)
},
},
watch: {
theadData: {
handler(vv) {},
deep: true,
}
},
}
</script>
<style>
.el-table__body-wrapper tr:hover .mp-highlight {
color: #2579ff;
cursor: pointer;
}
.el-tooltip__popper {
max-width: 800px;
}
td.mp-highlight:hover {
color: #2579ff;
cursor: pointer;
}
.el-table__header thead th .cell .el-table__column-filter-trigger i.el-icon-arrow-down {
position: absolute;
top: 6px;
left: auto;
color: #666;
transform: scale(1);
}
.el-table__header thead th .cell .el-table__column-filter-trigger i.el-icon-arrow-down:before {
content: '\e790';
}
.mp-custom-table {
font-size: 14px;
/* border-radius:10px; */
}
.el-table__header-wrapper {
border-radius: 0;
}
.el-table__header-wrapper .cell .el-icon-info {
cursor: pointer;
opacity: 0.4;
}
.el-table__header-wrapper .cell .el-icon-info:hover {
opacity: 0.8;
}
/* .el-table__body-wrapper{
border-radius:10px;
} */
.el-table--border th {
border-right: none;
}
.el-table--border td {
border-right: none;
}
.mp-custom-table .el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: RGBA(247, 248, 252, 1) !important;
}
.mp-list.mp-custom-table .el-table__body-wrapper tr:hover td {
background-color: RGBA(231, 244, 255, 1) !important;
}
.mp-custom-table .el-table--border,
.el-table--group {
border-left: none;
border-right: none;
border-top: none;
}
.mp-custom-table .el-table--border::after,
.el-table--group::after,
.el-table::before {
background-color: transparent !important;
}
.mp-custom-table.el-table .el-table__body-wrapper {
padding-bottom: 0px;
}
.mp-custom-table.el-table .el-table__fixed-right {
height: calc(100% - 10px) !important;
}
.mp-custom-table.el-table .el-table__fixed-right::before {
background-color: transparent !important;
}
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar {
width: 5px;
height: 8px;
background-color: #fff;
border-radius: 5px;
border-left: none;
}
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-track,
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
border-radius: 999px;
}
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-track {
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2) inset;
}
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
background-clip: content-box;
background: rgba(0, 0, 0, 0.01);
box-shadow: none;
}
/* .el-table.mp-custom-table
.el-table__body-wrapper:hover::-webkit-scrollbar-thumb {
background: red;
} */
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-corner {
background: transparent;
}
.mp_tatble_nodata {
/* padding: 40px 0; */
display: flex;
align-items: center;
flex-flow: column;
justify-content: center;
}
.mp_noData_image {
width: 80px;
height: 80px;
}
.mp_tatble_txt {
font-size: 14px !important;
}
</style>
<style>
.mp-list.mp-custom-table .el-table__header thead tr th {
background: rgba(242, 244, 248, 1) !important;
color: rgba(68, 79, 89, 1) !important;
}
.eveningTheme .el-table__body-wrapper tr:hover .mp-highlight {
color: #07f6ff !important;
}
</style>
<style lang="scss" scoped>
.eveningTheme {
.el-table__body-wrapper tr:hover .mp-highlight {
color: #07f6ff !important;
}
.mp-custom-table ::v-deep .el-table__header thead tr th {
background: #062540 !important;
// color:#fff !important;
}
.mp-custom-table {
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: #062540 !important;
}
::v-deep .el-table__body-wrapper tr:hover td,
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped:hover td {
background-color: #153864 !important;
}
::v-deep .el-table__body-wrapper tr:hover .mp-highlight {
color: #07f6ff;
cursor: pointer;
}
::v-deep td.mp-highlight:hover td {
color: #07f6ff;
cursor: pointer;
}
::v-deep .el-table__body-wrapper {
&::-webkit-scrollbar {
width: 5px;
height: 5px;
background-color: transparent;
border-radius: 5px;
border-left: none;
&-track {
background-color: #020919;
}
&-thumb {
background-color: #07639d;
}
}
}
::v-deep .el-table__body-wrapper:hover {
&::-webkit-scrollbar {
&-thumb {
background-color: #153864;
}
}
}
::v-deep.el-table {
tr {
background-color: #020919 !important;
}
}
}
}
::v-deep .mp-disabled-row,
::v-deep .mp-list.mp-custom-table .el-table__body-wrapper tr.mp-disabled-row:hover,
::v-deep .mp-custom-table .el-table--striped .el-table__body tr.el-table__row--striped.mp-disabled-row {
td {
//border-top: 1px dashed rgba(62, 127, 255, 1);
border-bottom: 1px dashed rgba(62, 127, 255, 1);
background: rgba(62, 127, 255, 0.2) !important;
}
}
</style>
<style lang="scss">
.eveningTheme {
.mp-list.mp-custom-table .el-table__header thead tr th {
background: #071d30 !important;
// color:rgba(68, 79, 89, 1) !important;;
}
}
</style>
- 组件简单使用 (基本常用的属性方法都已封装进去 , 可自行查看 tableList.vue )
(如果缺少需要的功能,可自行补充,或者留言)
javascript
/**
:selecShow="true" // 开启复选框
:tableData="dataTableListInfo" // 表格数据
:theadData="option.column" // 表格头部
:fullLoading="loading" // 表格loading
@queryRow="selectDataTable" // 表格多选事件
@handleClickRow="getHandleClickRow" // 行点击事件
*/
<template>
<div>
<table-operation
class="mp-custom-table"
:selecShow="true"
:tableData="dataTableListInfo"
:theadData="option.column"
:fullLoading="loading"
@queryRow="selectDataTable"
@handleClickRow="getHandleClickRow"
ref="tableRef"
>
// 该字段使用了插槽 对数据做了处理
<template slot="keyNode" slot-scope="{ row }">
<span>{{ row['keyNode'] == 1 ? '否' : '是' }}</span>
</template>
// 表格按钮组
<el-table-column slot="operbtn" label="操作" width="160" fixed="right">
<template slot-scope="{ row }">
<mp-button type="text" class="mp-button_edit-custom mp-button_table-typeA-custom" @click="editFormTable(row)">编辑</mp-button>
<mp-button type="text" class="mp-button_edit-custom mp-button_table-typeA-custom" @click="deleteFormTable(row)">删除</mp-button>
</template>
</el-table-column>
</table-operation>
// 分页组件
<mp-pagination :pageIndex="pageIndex" :pageSize="pageSize" :total="total" @page-change="pageChange" @page-size-change="pageSizeChange"></mp-pagination>
</div>
</template>
<script>
import TableOperation from '@/custom/tableList' // 引入上面的表格组件
export default {
components: {
TableOperation,
},
data() {
return {
dataTableList: [],
loading: false,
pageIndex: 1, //页码
pageSize: 10, //分页条目数
total: 0, // 总条数
option: {
column: [
{
field: 'indexName',
highlight: true, // 鼠标移入表格行后,指标名称字段高亮 点击指标名称 跳转
title: '指标名称',
// 给列表的th添加提示icon,鼠标进过后显示tooltip,配置theadData时,配置headerTip内容,则展示到此,未配置不展示icon
headerTip: '检测内容定义的名称',
},
{
field: 'indexCode',
title: '唯一标识',
headerTip: 'cmdb 中字段唯一标识',
},
{
field: 'keyNode',
title: '是否关键指标',
headerTip: '标记',
// 该字段是否使用插槽
isSlot: true, //插槽
}
],
}, // 表头
}
},
methods:{
// 编辑
editFormTable(row){},
deleteFormTable(row) {
// 这里是表格行删除事件
},
// 多选
selectDataTable(row, data) {
},
// 每一行的指标名称点击事件
getHandleClickRow(row) {
},
// 分页
pageChange(pageIndex) {
this.pageIndex = pageIndex
},
// 分页每页条数
pageSizeChange(pageSize) {
this.pageIndex = 1
this.pageSize = pageSize
},
}
}
</script>
-
效果
-
扩展(分页组件)
- 在 custom 文件夹下 新建 mpPagination.vue
- 上代码
javascript
// mpPagination.vue
<template>
<!-- 分页 -->
<div class="avue-crud__pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageIndex"
:page-sizes="pageSizeOption"
:page-size="pageSize"
:pager-count="showPagingCount"
:layout="layout"
:total="total"
:key="keyIndex"
>
</el-pagination>
</div>
</template>
<script>
export default {
name: 'MpPagination',
props: {
index:{
type:Number,
default:0
},
//总条数
total: {
type: Number,
default: 0,
},
//当前页
pageIndex: {
type: Number,
default: 1,
},
//页码按钮的数量,当总页数超过该值时会折叠
showPagingCount: {
type: Number,
default: 7,
},
//每页条目数
pageSize: {
type: Number,
default: 10,
},
//配置功能布局
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper',
},
//选择每页条目数
pageSizeOption: {
type: Array,
default() {
return [10, 20, 50]
},
},
},
data() {
return {
keyIndex:0
}
},
methods: {
//每页条目数改变
handleSizeChange(val) {
this.$emit('page-size-change', val,this.index)
},
//当前页改变
handleCurrentChange(val) {
this.$emit('page-change', val,this.index)
},
},
}
</script>
- 以上为全部代码!