vue2 el-table 封装
- 在 custom 文件夹下面创建 tableList.vue
- 直接上代码(代码比较多,复制可直接用)
<template><div class="mp-list"><el-tableref="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高度,接收StringtableHeight: {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 = rowarr.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 = trueif (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 )
(如果缺少需要的功能,可自行补充,或者留言)
/**:selecShow="true" // 开启复选框:tableData="dataTableListInfo" // 表格数据:theadData="option.column" // 表格头部:fullLoading="loading" // 表格loading@queryRow="selectDataTable" // 表格多选事件@handleClickRow="getHandleClickRow" // 行点击事件*/
<template><div><table-operationclass="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内容,则展示到此,未配置不展示iconheaderTip: '检测内容定义的名称',},{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 = 1this.pageSize = pageSize},}
}
</script>
-
效果
-
扩展(分页组件)
- 在 custom 文件夹下 新建 mpPagination.vue
- 上代码
// 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>
- 以上为全部代码!