侧边栏壁纸
博主头像
M酷博主等级

祝君一帆风顺 ⛵️⛵️⛵️

  • 累计撰写 40 篇文章
  • 累计创建 36 个标签
  • 累计收到 240 条评论

目 录CONTENT

文章目录

el-table 添加行内操作时,列宽不够如何处理

M酷
2021-09-13 / 2 评论 / 12 点赞 / 691 阅读 / 2,910 字 / 正在检测是否收录...

背景

最近项目中有一个需求是列表里面有一些敏感字段,一开始不想直接展示出来,需要用户手动去请求解密接口才展示,而且并非整列解密,而是单个数据解密,这就需要行内操作了。

UI对应该需求出了如下一张图:
el-table-sj

过程

从图中可以看到,需要在字段内容后面增加一个眼睛图标,可以切换显示内容。

起初我觉得是很容易的一个需求,直接就对当前 column 做了自定义的渲染,把内容和图标放在了单独的元素中,内容使用了单行省略的形式来做。
解密状态下点击眼睛请求解密接口得到真实的值并缓存在标签上(下次点击就不用再请求解密接口),再次点击闭眼图标,还原为加密的值。这里都是使用的 dom 操作,方便快捷。

效果也做出来了,但是后来产品说列宽可以自由拖拽调整,el-table 默认就可以拖拽调整列宽,我测试了一下,发现图标和内容在列宽比较窄的情况下,样式会出问题。而且有时候表格的 tooltip 并不会出现,导致内容截断时无法查看完整内容,如图:
el-table-wt

分析

简单分析了一下,主要有这样几个问题要解决:

  1. 在保持内容和图标居中的情况下,如何适配列宽变化?
  2. 保证表格的 tooltip 在内容展示不全时生效

解决

经过一些调试,发现可以用 flex 布局配合一点小技巧来解决:
表格 column 自定义模板部分如下:

<span class="tb-title-decrypt" v-if="data.item.encryption && ![null, ''].includes(data.row[data.item.prop])">
    <span class="tb-value">{{ data.row[data.item.prop] }}</span>
    <span class="icon-holder">
    	<svg-icon icon-class="eye" @click="data.item.toggleField(data.item, data.row, $event, 'show')" />
    	<svg-icon icon-class="eye-close" @click="data.item.toggleField(data.item, data.row, $event, 'hide')" />
    </span>
</span>

解密方法如下:

async toggleField(column, row, e, type) {
    const parentNode = e.currentTarget.parentNode.parentNode;
    const valueNode = parentNode.querySelector(".tb-value");
    if (type === "show") {
        const tagVal = parentNode.getAttribute("data-val");
        if (tagVal) {
            // 标签上有内容直接取就可以,不用再请求接口
            parentNode.classList.add("decrypted");
            valueNode.innerHTML = tagVal;
            return;
        }
        await this.$api.user
            .encryptionField({
                id: row.id,
                code: column.prop,
            })
            .then((res) => {
                const val = res.data || "-";
                parentNode.setAttribute("data-val", val); // 缓存真实内容到标签上
                parentNode.classList.add("decrypted");
                valueNode.innerHTML = val;
            });
        return;
    }
    parentNode.classList.remove("decrypted");
    valueNode.innerHTML = row[column.prop];
}

对应的样式如下:

.tb-title-decrypt {
    position: relative;
    text-align: center;
    display: flex;
    width: 110%; // 这个宽度是为了让表格 tooltip 提前一点生效,保证可以看到完整内容
    justify-content: center;
    align-items: center;
    .tb-value {
      position: relative;
      display: inline-block;
      padding-right: 15px;
      vertical-align: middle;
      overflow: hidden;
      white-space: nowrap;
      // 这里很关键,在宽度不够时我使用了一个渐变来遮住内容,没用单行省略号来做(有坑)
      &:after {
        position: absolute;
        right: 0;
        content: "";
        width: 20px;
        height: 100%;
        background: linear-gradient(to right, transparent, #fff 50%);
      }
    }
    .icon-holder {
      position: relative;
      z-index: 2;
      display: inline-block;
      margin-left: -10px; // 图标部分往前移一点,这样看起来不会离内容太远
    }
    svg {
      display: none;
      cursor: pointer;
      font-size: 16px;
      fill: #666;
      &:hover {
        fill: #1863fb;
      }
    }
    .icon-eye {
      display: inline-block;
    }
    &.decrypted {
      .icon-eye {
        display: none;
      }
      .icon-eye-close {
        display: inline-block;
      }
    }
  }

最终得到如下效果:
el-table-xg

工作上遇到的一些问题,简单记录一下,如果你也遇到了,希望也能给你一点启发。

12
广告 广告

评论区