vxe-table table tooltip 超长无法显示完全 + 无法滚动问题

背景:

客户喜欢把大段对话粘贴到系统, 表格里要 tooltip 显示这些对话全文, 而 vxe-table(项目里用的版本是 ^3.7.5) 仅设置了 tooltip 样式 max-width 600 , 导致 tooltip 内部没法滚动, 大段对话也显示不全, 影响客户使用

探索:

  1. 全局样式给 tooltip 加上 max-height 和 overflow-y: auto , 显示滚动条了, 但是…没法滚动, 滚动一下表格就直接滚动 + 关闭 tooltip 了

  2. github 找 vxe-table 源码看, 发现它是监听 mousewheel , 尝试在页面上选中 tooltip , addEventListener mousewheel 然后 e.stopPropagation() , 成功只滚动 tooltip 内容 + 不滚动表格

  3. 根据上一步的发现, 想办法给 tooltip element 加上 onmousewheel 和 stopPropagation , 在 api 中找到 cell-mouseleave 事件, 测试发现鼠标离开单元格进入单元格触发的 tooltip 中也会触发此事件, 因此监听此事件, 在此事件回调中, 选中 tooltip , 加上 onmousewheel = e => e.stopPropagation();, 成功实现"tooltip 内滚动不触发表格的滚动"

  4. 发现新问题 — 切换不同单元格触发 tooltip , tooltip 内的滚动条位置不会复位/重置

  5. 为解决新问题, 尝试:

    1. 直接在 cell mouseleave 时, 重置 tooltip scrollTop ;

      不可行, 这样会导致鼠标离开 tooltip 回到 cell 时 tooltip 滚动条也重置了, 理想情况应该是彻底离开 cell 关闭 tooltip 时重置 tooltip, 保证进入新 cell 打开 tooltip 时滚动条重置

    2. 如果 cell mouseleave 时, 能判断 tooltip 即将消失, 则可以在此时重置 tooltip 的 scrollTop;

      不可行, 离开旧 cell 进入新 cell 时, 会触发 cell mouseleave , 但此时 vxe-table 实例数据的 $table.tooltipStore.visible 和 $refs.tooltip.visible 都为 true , 根本没办法判断旧 cell 的 tooltip 是否关闭

    3. 尝试 cell mouseenter

      可行, 进入新 cell 时, $table.tooltipStore.visible 为 true , $refs.tooltip.visible 为 false , 说明此时 table 设置了要显示 tooltip 但尚未生效, 因此可以在此时重置 tooltip scrollTop

    4. 在 cell mouseenter 重置 tooltip scrollTop 未生效?

      搜索发现, 这是因为 tooltip 显示出来之前, 是 display none 状态, 此时即便设置 scrollTop 也不生效; 因此, 改为先设置 tooltip visibility hidden , setTimeout 等 tooltip 显示之后再重置 scrollTop + 恢复 visibility visible

      (setTimeout 的时间, 试了下, 500 不行, 600 可以, 看了下源码, 没主动设置 table 的 tooltip 的 enterDelay 的话, 就会使用 tooltip 的默认 enterDelay: 500)

    5. 最后, 为了避免快速在不同 cell 移动触发 tooltip 时 timeout 不合时宜地执行, 需要暂存 timeout id , 每次打开新 tooltip 时清除旧 timeout 重置 timeout

具体代码:

// template
<vxe-table
	//...
    @cell-mouseenter="handleCellMouseEnter"
    @cell-mouseleave="handleCellMouseLeave"
>...</vxe-table>

// variables
// 延时显示 vxe-table tooltip 计时器 id
timeout_showTooltip: null

// methods
// vxe-table 的 tooltip 加上滚动条后, tooltip 关闭再打开, 滚动条仍然在之前 tooltip 滚动到的位置
// 因此给 tooltip 的滚动主体加上 scrollTop 置空
handleCellMouseEnter({ $table }) {
    // 取 tooltip 实例
    const $tooltip = $table && $table.$refs && $table.$refs.tooltip;
    if ($tooltip && $tooltip.$el) {
        // 如果此时设置了 tooltip 要显示但尚未生效, 则延时显示 tooltip , 避免 tooltip 内滚动条还未重置
        // 注意, 此处是"鼠标移入单元格, 即将显示 tooltip"场景, 在此处处理 scrollTop 重置
        // 不在 mouseleave 处理, 是因为 mouseleave 时这两个数据不准, 从一个有 tooltip 的 cell 移动到下一个, 这两个数据仍然是 true , 因此无法做到"鼠标移出单元格, tooltip 即将关闭, 此时重置 scrollTop"
        if ($table.tooltipStore.visible && !$tooltip.visible) {
            // 清除旧延时, 避免快速切换 tooltip 时, tooltip 的滚动条还未重置就显示出来了
            if (this.timeout_showTooltip) {
                clearTimeout(this.timeout_showTooltip);
            }
            // 延时显示 tooltip
            this.delayShowTooltip($tooltip.$el);
        }
    }
},
// 延时显示 vxe-table tooltip
// 因为 tooltipEl 为 display none 状态时设置 scrollTop 无效, 所以先通过 visibility 隐藏 tooltip , 重置 scrollTop 完毕后再恢复 visible
delayShowTooltip(tooltipEl) {
    // 取 tooltip 滚动主体元素
    const tooltipContentEl = tooltipEl.querySelector('.vxe-table--tooltip-content');
    if (tooltipContentEl) {
        tooltipEl.style.visibility = 'hidden';
        this.timeout_showTooltip = setTimeout(() => {
            tooltipContentEl.scrollTop = 0;
            tooltipEl.style.visibility = 'visible';
            this.timeout_showTooltip = null;
        }, 600); // 延时 600 是因为 tooltip 默认 enterDelay 为 500 , 低于 500 会因为 tooltip el 尚未 display , 导致 scrollTop 设置仍然无效
    }
},
// vxe-table 的 tooltip , 存在"内部滚动条滚动时触发 table 的 mousewheel 事件, 导致 table 主动关闭 tooltip"问题
// 因此给 tooltip 滚动主体加上 mousewheel stopPropagation , 停止向上传递 mousewheel 事件给 table
handleCellMouseLeave({ $table }) {
    // 取 tooltip 实例
    const $tooltip = $table && $table.$refs && $table.$refs.tooltip;
    if ($tooltip && $tooltip.$el) {
        // 取 tooltip 滚动主体元素
        const tooltipContentEl = $tooltip.$el.querySelector('.vxe-table--tooltip-content');
        if (tooltipContentEl && !tooltipContentEl.onmousewheel) {
            tooltipContentEl.onmousewheel = e => e.stopPropagation();
        }
    }
}

// css
.vxe-table--tooltip-wrapper .vxe-table--tooltip-content {
    max-width: 600px;
    max-height: 210px;
    overflow-y: auto;
}

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值