基于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
            }
        }
    }
})
posted @ 2021-09-07 17:10  HeSh  阅读(2182)  评论(0编辑  收藏  举报