在一行或多行中显示多个标签,超过范围就省略。这种场景跟文本超出限制显示省略号,还是有点区别:
- 单个标签是无法截断和换行的,不像文本一样有原生的 CSS 属性支持;
- 当超出限制时,还得需要留出空间给到省略号;
像这种场景就不能用 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);
};
这样就计算出省略标签要放置的位置了。
若需要对标签频繁的增删调整,为了能重新计算新的隐藏标签的位置,需要重新显示出所有标签,然后重新计算。