个人技术分享

vue2+elementui 实现表格中操作列不定个数按钮的折叠展开,可以根据自己的需求自行修改样式和展示等。基本代码如下:

<template>
    <div class="table-action-col-box" :ref="`_bf+${rowId}`">
        <div :ref="`_bf+${rowId}_button`">
            <slot></slot>
        </div>
        <el-popover popper-class="table-action-btn-pop" :placement="placement" width="auto" :trigger="trigger" :ref="`popover_bf+${rowId}`">
            <div class="table-action-btn-pop-content">
                <slot></slot>
            </div>
            <template slot="reference">
                <span v-show="isFold">
                    <slot v-if="$slots.popoverReference" name="popoverReference"></slot>
                    <i v-else class="el-icon-more fold-icon" :style="{ marginLeft: `${buttonGap}px` }"></i>
                </span>
            </template>
        </el-popover>
    </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Ref, PropSync } from 'vue-property-decorator';
@Component({
    components: {}
})
export default class TableActionCol extends Vue {
    @Prop({ default: null }) rowId: number | string;
    @Prop({ default: 2 }) maxLength: number; // 最多展示按钮的个数,不包含更多按钮
    @Prop({ default: 'bottom' }) placement: string;
    @Prop({ default: 'hover' }) trigger: string;
    @Prop({ default: 10 }) buttonGap: number;

    protected isFold: boolean = false;
    protected currentRowMaxLength = 2;

    mounted() {
        this.currentRowMaxLength = this.maxLength;
        this.domInit();
    }

    protected domInit() {
        this.$nextTick(() => {
            let children = (this.$refs[`_bf+${this.rowId}_button`] as any)?.children || [];
            const newChildren = Array.from(children);
            let popoverChildren = (this.$refs[`popover_bf+${this.rowId}`] as any)?.$refs?.popper?.children || [];
            const popoverButtons = popoverChildren && popoverChildren[0]?.children;

            for (let k = 0, len = children.length; k < len; k++) {
                if (children[k].style.display == 'none') {
                    this.currentRowMaxLength++;
                    newChildren[k] = 'none';
                    continue;
                }
                if (k > this.currentRowMaxLength - 1) {
                    children[k].style.display = 'none';
                }
            }

            // popover是否展示
            this.isFold = newChildren.filter(item => item != 'none')?.length > this.maxLength;

            // popover元素
            for (let k = 0, len = popoverButtons.length; k < len; k++) {
                if (children[k].style.display != 'none') {
                    popoverButtons[k].style.display = 'none';
                }
            }
        });
    }
}
</script>
<style lang="scss" scoped>
.table-action-col-box {
    display: flex;
    align-items: center;
    .fold-icon {
        cursor: pointer;
    }
}
</style>
<style lang="scss">
.table-action-btn-pop {
    padding: 12px 0;
    .table-action-btn-pop-content {
        display: flex;
        flex-direction: column;
    }
    .el-button {
        margin-left: 0;
    }
}
</style>