基于ElementUi封装table组件——包含表头工具栏、多级表头、合并行、分页
表格组件WTable.vue
<template> <div class="wTable"> <!-- 头部工具栏 --> <div v-if="tools && tools.length>0 && tools[0].label" class="toolBar"> <template v-for="(tool, key) in tools"> <!-- 具名插槽 --> <slot v-if="tool.slot" :name="tool.slot" /> <el-button v-else :key="key" :type="tool.type" :size="tool.size" :plain="tool.plain" :round="tool.round" :circle="tool.circle" :icon="tool.icon" :style="tool.style" :disabled="tool.disabled" @click.native.prevent="tool.method()" > {{ tool.label }} </el-button> </template> </div> <!-- 表格 --> <el-table id="wTable" ref="wTable" v-loading.wTable="woptions.loading" v-tableDrag :data="data" :height="tHeight" :stripe="woptions.stripe" :border="woptions.border" :fit="woptions.fit" :span-method="spanMethod" :row-key="rowKey" @selection-change="handleSelectionChange" > <!-- 多选框 --> <el-table-column v-if="woptions.mutiSelect" :reserve-selection="true" type="selection" :selectable="woptions.checkSelect" style="width: 55px;" align="center" /> <!-- 序号 --> <el-table-column v-if="woptions.index" label="序号" type="index" style="width: 55px;" align="center" /> <!-- 数据列 --> <template v-for="(column, index) of columns"> <!-- 如过有嵌套,递归多级表头 --> <template v-if="column.children && column.children.length > 0"> <WColumn :key="index" :column="column" /> </template> <!-- 没有正常显示 --> <template v-else> <!-- 具名插槽 --> <slot v-if="column.slot" :name="column.slot" /> <el-table-column v-else-if="!column.isHide" v-slot="scope" :key="index" :prop="column.prop" :label="column.label" :type="column.type" :min-width="column.minWidth" :width="column.width" :align="column.align" :fixed="column.fixed" :show-overflow-tooltip="column.tooltip" :class-name="column.class" :sortable="column.sort" > <!-- 是否需要特殊处理 --> <template v-if="column.formatter"> <span v-html="column.formatter(scope.row, column)" /> </template> <template v-else> <!-- 正常显示 --> <span>{{ scope.row[column.prop] }}</span> </template> </el-table-column> </template> </template> </el-table> <!-- 分页 --> <div v-if="isPagination" class="pagination"> <el-pagination background :current-page="wpagination.currentPage" :page-sizes="wpagination.pageArr" :page-size="wpagination.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </div> </div> </template> <script> /** * 使用方法: * 通用的可参考 views/businessManage/businessList * 多级表头可参考 views/dingdang/privacyCallInfo * 合并行可参考 views/codeManage/routeTest */ import WColumn from './WColumn' export default { name: 'WTable', components: { WColumn }, props: { // 头部按钮组 tools: { type: Array, default() { return [ {method() {}} ] } }, // 数据 data: { type: Array, requre: true, default() { return [] } }, // 合并行 spanMethod: Function, // 多选回显key rowKey: { type: String, default: 'id' }, /** * 表格默认配置 * height: 表格高度 * stripe: 是否为斑马纹 table * border: 是否带有纵向边框 * fit: 列的宽度是否自撑开 * mutiSelect: 是否开启多选 * loading: 添加loading */ options: { type: Object, default() { return { stripe: true, border: false, fit: true, mutiSelect: false, loading: false, index: true } } }, // 表格高度 tHeight: { type: Number, default: 200 }, /** * 列集合 * prop: 列字段 * label: 列名称 * align: 文本显示位置 * width: 列固定宽度,例:200 * minWidth: 自适应宽度 例: 200 或 20% * type: 类型 * formatter: 特殊处理 * slot: 特殊列名称 * isHide: 是否隐藏列,用于动态展示列 * tooltip: 超出是否... * class: 列的class * sort: 是否排序 */ columns: { type: Array, default() { return [] }, require: true }, // 数据总数 total: { type: Number, default: 0 }, // 是否显示分页 isPagination: { type: Boolean, default: true }, /** * 分页参数 * pagesize:每页显示的条数 * currentPage:当前页码 * pageArr: 显示多少条集合 * background: 是否要背景 */ pagination: { type: Object, default() { return { pagesize: 10, background: true, currentPage: 1, pageArr: [10, 20, 50, 100] } } } }, data() { return { // 默认的表格配置 woptions: { stripe: true, border: false, fit: true, mutiSelect: false, loading: false, index: true, checkSelect() { return true } }, // 默认的分页配置 wpagination: { pagesize: 10, background: true, currentPage: 1, pageArr: [10, 20, 50, 100] } } }, created() { // 扩展配置,目的是引用组件不用把配置全写一遍 this.woptions = Object.assign({}, this.woptions, this.options) this.wpagination = Object.assign({}, this.wpagination, this.pagination) }, methods: { // 表格多选 handleSelectionChange(val) { this.$emit('handleSelectionChange', val) }, // 选择每页展示的条数 handleSizeChange(size) { this.$emit('handleSizeChange', size) }, // 点击第几页 handleCurrentChange(currentPage) { this.$emit('handleCurrentChange', currentPage) } } } </script> <style lang="scss" scoped> .wTable { box-shadow: 0 0 10px #eee; .toolBar { padding: 10px; overflow: hidden; } .pagination { padding: 30px 0; text-align: center; } #table { width: 100%; } } </style>
多级表头递归子组件WColumn.vue
<template> <el-table-column v-if="!column.isHide" :prop="column.prop" :label="column.label" :type="column.type" :min-width="column.minWidth" :width="column.width" :align="column.align" :fixed="column.fixed" :show-overflow-tooltip="column.tooltip" :class-name="column.class" :sortable="column.sort" > <!-- 数据列 --> <template v-for="(item, key) of column.children"> <template v-if="item.children && item.children.length > 0"> <WColumn :key="key" :column="item" /> </template> <template v-else> <!-- 具名插槽 --> <slot v-if="item.slot" :name="item.slot" /> <el-table-column v-else-if="!item.isHide" v-slot="scope" :key="key" :prop="item.prop" :label="item.label" :type="item.type" :min-width="item.minWidth" :width="item.width" :align="item.align" :fixed="item.fixed" :show-overflow-tooltip="item.tooltip" :class-name="item.class" :sortable="item.sort" > <!-- 是否需要特殊处理 --> <template v-if="item.formatter"> <span v-html="item.formatter(scope.row, item)" /> </template> <template v-else> <!-- 正常显示 --> <span>{{ scope.row[item.prop] }}</span> </template> </el-table-column> </template> </template> </el-table-column> </template> <script> export default { name: 'WColumn', props: { column: { type: Object, default() { return {} } } } } </script>
自定义点击表格横向滚动指令v-tableDrag
main.js将directices.js引入即可
import Vue from 'vue'
Vue.directive('tableDrag', {
inserted: function(el) {
el = el.getElementsByClassName('el-table__body-wrapper')[0]
el.style.cursor = 'grab'
el.onmousedown = function() {
let gapX = event.clientX
let startX = el.scrollLeft
document.onmousemove = function(e) {
let x = e.clientX - gapX
el.scrollLeft = startX - x
return false
}
document.onmouseup = function() {
document.onmousemove = null
document.onmouseup = null
}
}
}
})