el-table操作列不定按钮超过个数自动收起

1,233 阅读3分钟

功能说明

el-table中有一个操作列,每一行根据数据情况有不同数量和功能的按钮,要求超过三个按钮的行,超出按钮收起为更多按钮,鼠标移入再展示

  • 每行按钮的个数不定,每个按钮的展示条件不同,且判断条件很复杂
  • 按钮功能不同
  • 按钮不仅有单个展示条件,还有分组条件

download.png

解决思路

  • 根据按钮生成条件进行分组
    • 方案1:
      1. 将按钮复制一份,分成外部展示和下拉展示两组
      2. 通过判断条件得到所有需要生成的按钮下标
      3. 页面中判断
    • 优点:
      1. 页面动态渲染,不需要操作dom
    • 缺点
      1. 判断条件太多且比较难以组合
      2. 每一行都要经过计算,计算量大
      3. 不具备通用性
  • 通过操作dom对按钮进行分组
    • 方案2:
      1. 将所有按钮放到一个容器中,在按钮上绑定自定义指令
      2. 通过自定义指令获取生成的容器以及按钮子元素
      3. 根据子元素个数与内容对重新生成dom并绑定事件,然后插入到页面中
    • 优点:
      1. 方法可各个页面复用,且只需要加上自定义指令,系统较大时改动量小
      2. 比较容易想到
    • 缺点
      1. 性能消耗太大
  • 通过css和自定义指令对按钮显示进行控制
    • 方案3:
      1. 将按钮复制一份,分成外部展示和下拉展示两组
      2. A组按钮全部进行隐藏,仅显示前三个子节点
      3. B组按钮隐藏前三个子节点
      4. 给B组按钮容器加上自定义指令,如果容器子节点少于4个,隐藏容器(更多按钮)
      5. B组按钮容器动态绑定key,否则el-table翻页或其它数据改变时,步骤4无法更新dom
    • 优点:
      1. 方法可各个页面复用,且只需要加上自定义指令,系统较大时改动量小
      2. 对dom的操作量少
      3. 性能消耗较小
      4. 代码较前两种方法更加简洁易懂
    • 缺点
      1. 需要生成两组按钮,有额外渲染

最终选择代码

VUE
<template slot-scope="scope">
    <div class="fd-link-group">
        <span @click="AAA(scope.row)" class="fd-table-link">AAA</span>
        <span @click="BBB(scope.row)" class="fd-table-link" v-if="a && b && c && d  && e">BBB</span>
        <template v-if="F">
            <span @click="CCC(scope.row)" v-if="A && F" class="fd-table-link">CCC</span>
            <span @click="DDD(scope.row)" v-if="!A" class="fd-table-link">CCC</span>
        </template>
        <span @click="EEE(scope.row, 1)" v-if="D && G && H class="fd-table-link">DDD</span>
        <span @click="FFF(scope.row)" v-if="M" class="fd-table-link">EEE</span>
        <span @click="GGG(scope.row)" v-if="N && H &&I" class="fd-table-link">FFF</span>
    </div>
    <div class="fd-link-drop" v-shwoLinkDrop :key="scope.row.cbh">
        <div class="fd-link-drop-content">
            <div class="fd-link-drop-body">
                <span @click="AAA(scope.row)" class="fd-table-link">AAA</span>
                <span @click="BBB(scope.row)" class="fd-table-link" v-if="a && b && c && d  && e">BBB</span>
                <template v-if="F">
                    <span @click="CCC(scope.row)" v-if="A && F" class="fd-table-link">CCC</span>
                    <span @click="DDD(scope.row)" v-if="!A" class="fd-table-link">CCC</span>
                </template>
                <span @click="EEE(scope.row)" v-if="D && G && H" class="fd-table-link">DDD</span>
                <span @click="FFF(scope.row)" v-if="M" class="fd-table-link">EEE</span>
                <span @click="GGG(scope.row)" v-if="N && H && I" class="fd-table-link">FFF</span>
            </div>
        </div>
    </div>
</template>
LESS
.fd-link-group {
    display: inline-block;
}

.fd-link-group .fd-table-link {
    display: none;

    &:first-child,&:nth-child(2),&:nth-child(3) {
        display: inline;
    }
}

.fd-link-drop {
    position: relative;
    z-index: 2;
    display: inline-block;
    width: 14px;
    height: 14px;
    background: url("~@/A.png") center no-repeat;
    background-size: 14px 14px;
    cursor: pointer;

    &:hover {
        z-index: 3;

        .fd-link-drop-content {
            display: block;
        }
    }
}

.fd-link-drop-content {
    position: absolute;
    top: 14px;
    right: -25px;
    display: none;
    padding-top: 10px;
    min-width: 126px;

    .fd-link-drop-body {
        border-radius: 2px;
        border: 1px solid #dbdddf;
        box-shadow: 0 9px 28px rgba(0, 0, 0, 0.05);
        background-color: #fff;
    }

    .fd-table-link {
        display: block;
        padding-left: 10px;
        width: 100%;
        height: 30px;
        color: rgba(0, 0, 0, 0.65);
        font: 12px/30px "microsoft yahei";

        &:hover {
            color: #2a95ff;
            background-color: #dcecff;
        }

        &:first-child,&:nth-child(2),&:nth-child(3) {
            display: none;
        }
    }
}
自定义指令
// 注册一个全局自定义指令 v-shwoLinkDrop,判断是否展示【更多】列表操作按钮
Vue.directive('shwoLinkDrop', {
    bind: function (el) {
        if ($(el).find('.fd-table-link').length < 4) {
            $(el).hide();
        }
    }
});

结语

虽然最终实现了,但我总感觉有更好的方案没想到,前两种方案受固有思维影响,不建议采用,第三种方案算是自己的一种另辟蹊径吧,可能实际项目中这种情况遇到的很少,更多的可能按钮可以通过data直接通过v-for进行渲染,这样的话就方便控制得多。