Wenzi

在 React 中显示多个标签,超出省略并可以 hover 显示更多

蚊子前端博客
发布于 2024/10/13 10:17
如何实现在一行或多行中显示多个标签,超过范围就省略

在一行或多行中显示多个标签,超过范围就省略。这种场景跟文本超出限制显示省略号,还是有点区别:

  1. 单个标签是无法截断和换行的,不像文本一样有原生的 CSS 属性支持;
  2. 当超出限制时,还得需要留出空间给到省略号;

像这种场景就不能用 CSS 来实现了,需要通过 JavaScript 计算出是否有标签超出范围,最后要留出多少空间给到省略号。

1. 如何判断有标签超出限制 #

设定容器固定的宽度和高度,高度为正好显示的行数,然后超出的部分进行隐藏。

首先默认渲染所有的标签,本来超出的数据也是隐藏的,从页面上是看不出异样的。然后查找某一个标签的位置超过容器的高度,那就说明有标签超出了。

const fn = () => {
  let index = tags.length; // 默认渲染所有的标签

  if (tags.length && tagContainer.current) {
    // 获取到素有的标签
    const doms: NodeListOf<HTMLElement> = tagContainer.current.querySelectorAll(".comment-item");

    // 获取容器的高度和宽度
    const { offsetHeight, offsetWidth } = tagContainer.current;

    // 计算从哪个标签开始就被隐藏了
    for (let i = 0; i < doms.length; i++) {
      if (doms[i].offsetTop > offsetHeight) {
        // 当前位置的标签已超出容器的范围
        console.log(i);
        break;
      }
    }
  }
  setShoTagLimit(index);
};

我们找到了第一个被隐藏的元素,接下来就得把「省略号」放到后面了。

2. 如何计算出省略号需要的宽度 #

这里我们不能直接使用上面计算出的数据,万一前面的标签正好铺满整行,或者剩余宽度太小无法容纳「省略号」,就会导致「省略号」被挤下去。因此还要再往前计算最后一行剩余的空间。

我们接着 for 循环里最后一个要显示的标签继续。

const fn = () => {
  let index = tags.length; // 默认渲染所有的标签

  if (tags.length && tagContainer.current) {
    // 获取到素有的标签
    const doms: NodeListOf<HTMLElement> = tagContainer.current.querySelectorAll(".comment-item");

    // 获取容器的高度和宽度
    const { offsetHeight, offsetWidth } = tagContainer.current;

    // 省略标签的宽度
    const ellipsisTagWidth = 40;

    // 计算从哪个标签开始就被隐藏了
    for (let i = 0; i < doms.length; i++) {
      if (doms[i].offsetTop > offsetHeight) {
        /**
         * 当前位置的标签已超出容器的范围。
         * 接下来该往前计算,更多按钮「...」应该放在哪个标签的后面。
         * 更多按钮的宽度加上标签后面的 marginRight 正好是 40px,若剩余空间大于40,
         * 则能容得下更多按钮,否则继续往前移动,直到能放得下省略按钮的位置
         */
        index = i - 1;
        while (index >= 0 && offsetWidth - doms[index].offsetLeft - doms[index].offsetWidth <= ellipsisTagWidth) {
          index--;
          break;
        }
        index++;

        break;
      }
    }
  }
  setShoTagLimit(index);
};

这样就计算出省略标签要放置的位置了。

若需要对标签频繁的增删调整,为了能重新计算新的隐藏标签的位置,需要重新显示出所有标签,然后重新计算。

标签:react
阅读(123)
Simple Empty
No data