惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
J
Java Code Geeks
H
Help Net Security
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
Microsoft Security Blog
Microsoft Security Blog
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
U
Unit 42
博客园 - 三生石上(FineUI控件)
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
小众软件
小众软件
博客园 - 叶小钗
D
Docker
量子位
P
Proofpoint News Feed
博客园_首页
T
Tailwind CSS Blog
F
Fortinet All Blogs

蚊子的前端博客

微说 | 有的人觉得只要不考XX,一定能考好!-蚊子的前端博客 微说 | 春天来了-蚊子的前端博客 明天和意外不知道哪个先来-蚊子的前端博客 微说 | 既然错过了路口,就及时止损,重新规划路线上路-蚊子的前端博客 微说 | 2025年的出生人口数是792万-蚊子的前端博客 微说 | 工作年终总结,让写对接的接口的数量?-蚊子的前端博客 微说 | 温家宝:没有政治体制改革的成功 经济体制改革不可能进行到底-蚊子的前端博客 微说 | 违法犯罪了该不该被禁言?-蚊子的前端博客 微说 | 不明白为什么在推荐去俄罗斯旅游-蚊子的前端博客 微说 | 易中天论骗子-蚊子的前端博客 微说 | 一场大风吹散了秋天-蚊子的前端博客 微说 | 既要、又要、还要、更要!-蚊子的前端博客 又是一年的国庆雨季-蚊子的前端博客 微说 | 预估下2025年的出生人口数据-蚊子的前端博客 微说 | 可惜了我那些小时候的书本-蚊子的前端博客 微说 | 牛马有的是,驴不够了!-蚊子的前端博客 微说 | 能否有一条非户口也能高考的路-蚊子的前端博客 微说 | 小聊中医-蚊子的前端博客 微说 | 将要制作的一款新产品-蚊子的前端博客 微说 | 做人要有信-蚊子的前端博客 微说 | 好一个正义联盟-蚊子的前端博客 微说 | 都是见过吃过的主儿-蚊子的前端博客 微说 | 追求8小时工作制有错吗?-蚊子的前端博客 微说 | 如果尖锐的批评完全消失-蚊子的前端博客 微说 | 很好!-蚊子的前端博客 微说 | 封禁用户可以,但要告知具体原因-蚊子的前端博客 微说 | 面朝大海,春暖花开-蚊子的前端博客 微说 | 程序员的悲哀是什么?-蚊子的前端博客 微说 | 2025年出生人口的预测-蚊子的前端博客 前端在 LiveKit 中如何获取所有的参与者-蚊子的前端博客
在 React 中显示多个标签,超出省略并可以 hover 显示更多-蚊...
author · 2024-10-13 · via 蚊子的前端博客

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

  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);
};

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

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