visactor vTable 在移动端支持 ellipsis 气泡

前言:

为了优化用户体验

VTable 内部在移动端故意屏蔽了省略号气泡的展示

本文旨在提供相对体验较好的移动端的 ellipsis 气泡展示完整信息的解决方案

1. 配置好 ref,以供引用

html 复制代码
<template>
    <VTable
      :id="uid"
      ref="tableRef"
      v-bind="$attrs"
    />
</template>
Typescript 复制代码
const tableRef = ref();

2. 判断当前 cell 是否是溢出的

Typescript 复制代码
function isCellTextOverflow(tableInstance: any, col: number, row: number): boolean {
  // getCellOverflowText 返回非空字符串说明有溢出
  const overflowText = tableInstance.getCellOverflowText(col, row);
  return !!overflowText;
}

3. 展示气泡

有 2 种方案,优缺点比较如下表:

气泡方案 VTable 原生气泡 自定义气泡
优点 配置简单 出现的位置不需要大量计算 长的好看 用户操作灵活 点击滚动等就会及时消失
缺点 样式丑 用户操作不灵活,不会及时消失 配置繁琐

3.1 VTable 原生气泡

3.1.1 开启 tooltip 开关

如果可以在初始化配置 VTableconfig 的话 直接在初始化的时候,把 config.tootip.isShowOverflowTextTooltip 配置为 true 即可。

如果开发没有配置 VTable config 的初始化权限的话,也可以在 VTable 初始化好后,通过 updateOption 来更新配置,注意不要覆盖掉原生的其他配置项。

Typescript 复制代码
const tableInstance = tableRef.value?.table;
tableInstance.updateOption({
    ...tableInstance.options,
    tooltip: {
      ...tableInstance.options.tooltip,
      isShowOverflowTextTooltip: true,
    }
});

3.1.2 监听用户的点击事件展示 tooltip

Typescript 复制代码
import { TABLE_EVENT_TYPE } from '@visactor/vtable';

tableInstance.on(TABLE_EVENT_TYPE.CLICK_CELL, (args: any) => {
    const isOverflow = isCellTextOverflow(tableInstance, col, row);
    if (!isOverflow) {
      return;
    }
    setTimeout(() => {
      // 调用内部 TooltipHandler 手动显示气泡
      // 注意:internalProps 是内部属性,使用时需要注意 TypeScript 类型兼容(如需)
      tableInstance.internalProps.tooltipHandler.showTooltip(col, row);
    }, 10);
});

点击有溢出的 cell,就会在 cell 附近展示出来的 VTable 原生的气泡了,长得还是有点丑的,如果要用的话,建议在 VTableoption 里加点样式的配置。

另外这个气泡的消失逻辑是 VTable 原生自己控制的,灵敏度也较一般,不会及时消失,有精力也可画时间监听优化,调用 VTable 原生函数的隐藏方法。

3.2 自定义 DIV 展示 tooltip

3.2.1 写个自定义的 div

HTML 复制代码
<div v-if="tooltipTxt" :style="{ left, top }" class="custom-popup">
  {{ tooltipTxt }}
</div>
Typescript 复制代码
const tooltipTxt = ref('');
const left = ref('0px');
const top = ref('0px');

配个好看点的气泡样式

SCSS 复制代码
.custom-popup {
  position: fixed;
  z-index: 10;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  border-radius: 4px;
  padding: 4px 8px;
  &::after {
    content: '';
    width: 0;
    height: 0;
    /* 边框宽度:上4px | 右4px | 下4px | 左0(仅右边框有宽度) */
    border-width: 4px 4px 4px 0;
    border-style: solid;
    /* 边框颜色:上透明 | 右灰色 | 下透明 | 左透明(仅右边框显示) */
    border-color: transparent #333 transparent transparent;
    /* 消除默认空白(避免字体/行高导致的间隙) */
    line-height: 0;
    font-size: 0;
    left: -6px;
    top: 0;
    bottom: 0;
    margin: auto;
    position: absolute;
  }
}

3.2.2 监听并且展示自定义气泡

Typescript 复制代码
tableInstance.on('click_cell', (args: any) => {
    // 先把旧的气泡干掉
    tooltipTxt.value = '';

    const { col, row, value } = args;

    // 过滤非数据行
    if (col < 0 || row < 0) return;

    // 判断是否溢出
    const isOverflow = isCellTextOverflow(tableInstance, col, row, value);

    if (!isOverflow) {
      return;
    }

    // 1. 获取列宽
    const colWidth = tableInstance.getColWidth(col);
    // 1. 获取列高
    const colHeight = tableInstance.getRowHeight(col);

    const { offsetX, offsetY } = args.event;
    left.value = offsetX - colWidth * 0.2 + 'px';
    top.value = offsetY - colHeight / 2 + 'px';
    tooltipTxt.value = value;
});

3.2.3 监听点击/滚动事件 隐藏气泡

Typescript 复制代码
import { TABLE_EVENT_TYPE } from '@visactor/vtable';

const hideTooltip = () => {
  if (tooltipTxt.value) {
    tooltipTxt.value = '';
  }
};

const tableInstance = tableRef.value?.table;const tableInstance = tableRef.value?.table;

tableInstance.on(TABLE_EVENT_TYPE.SCROLL, hideTooltip);
tableInstance.on(TABLE_EVENT_TYPE.RESIZE_COLUMN, hideTooltip);
// 监听树形结构变化(展开/折叠触发时也强制关掉,双重保险)
tableInstance.on(TABLE_EVENT_TYPE.TREE_HIERARCHY_STATE_CHANGE, hideTooltip);
// 如果你用了自动高度的方案,建议也监听 UPDATED
tableInstance.on(TABLE_EVENT_TYPE.UPDATED, hideTooltip);

onMounted(() => {
  window.addEventListener('scroll', hideTooltip, true);
});

onUnmounted(() => {
  window.removeEventListener('scroll', hideTooltip, true);
});

4. 总结

提供的两个解决思路性能消耗都不大,都可以满足需求。

相关推荐
用户28320967937几秒前
从进程线程到 async/await:JS Event-loop事件循环机制底层解析
前端·javascript
岁月宁静9 分钟前
一、《从零手撸 Agent》 我用 10 行代码跑通了第一次大模型调用(顺便踩了 4 个坑)
前端·python·agent
计算机魔术师28 分钟前
Fable 5.1 来了,智能体任务成本降 45%——Anthropic 这次为何降价这么狠
前端
Csvn29 分钟前
现代 CSS 新特性深度:container query、:has()、@scope 与 subgrid
前端
计算机魔术师34 分钟前
Anthropic 自己承认:模型越来越难管住了
前端
两只羊ovo43 分钟前
Agent 干活的底层地基:path 路径 + fs 文件系统,一次讲透
前端
一用书生43 分钟前
我给 ChatGPT、DeepSeek、Kimi 都加了一个「保存为笔记」按钮
前端·ai编程·vibecoding
咖啡无伴侣1 小时前
1. 从零搭建企业级 Monorepo 工程化模板:初始化、应用创建与共享 TypeScript 配置
前端·前端框架
moonsims1 小时前
再议AiBrainBox-V的前左右三目布局-满足多目SLAM算法;对比单下视VIO(低空、地面纹理丰富、飞行速度适中无人机 )&多目VIO
前端·人工智能·量子计算
AI编程实验室1 小时前
Agent Handoff 自动跟踪 Skill:安装、事件映射与证据分级
前端·ai编程