如果想要文本超出宽度后用省略号省略,只需要加上以下的css就行了。
1 | css复制代码.ellipsis { |
3行css搞定,但是问题来了:如果我们想要当文本被省略的时候,也就是当文本超出指定的宽度后,鼠标悬浮在文本上面才展示popper,应该怎么实现呢?
CSS帮我们搞定了省略,但是JS并不知道文本什么时候被省略了,所以我们得通过JS来计算。接下来,我将介绍几种方法来实现JS计算省略。
createRange
我发现Element-plus
表格组件已经实现了这个功能,所以就先来学习一下它的源码。
1 | ts复制代码// 仅仅粘贴相关的 |
1 | ts复制代码// 上面代码17行中的getPadding函数 |
document.createRange()
是 JavaScript 中的一个方法,用于创建一个 Range 对象,表示文档中的一个范围。Range 对象通常用于选择文档中的一部分内容,然后对其进行操作。
它可以:
- 设置选中文本范围:可以使用
document.createRange()
方法创建一个 Range 对象,并使用setStart()
和setEnd()
方法设置选中文本的起始和结束位置。 - 插入新元素:可以使用
document.createRange()
方法创建一个 Range 对象,并使用insertNode()
方法将新元素插入到文档中的指定位置。 - 获取特定元素的位置:可以使用
document.createRange()
方法创建一个 Range 对象,并使用getBoundingClientRect()
方法获取元素在文档中的位置和大小信息。
这边element就是使用range对象的getBoundingClientRect获取到元素的宽高,同时因为得到的宽高值有很多位的小数,所以element-plus做了一个判断,如果小数值小于0.001就舍弃小数部分。
接下来,就让我们进行一下复刻吧,可以通过调整盒子的宽度,在页面中看到是否有省略号的判断。
1 | html复制代码<div class="ellipsis box"> |
注意这里,我们需要区分clientWidth
和offsetWidth
,因为我们现在给了box加了1px的边框,所以offsetWidth = 1 * 2 (左右两边的border宽度) + clientWidth,所以我们这边使用clientWidth来代表box的实际宽度。
1 | js复制代码const checkEllipsis = () => { |
这种方法div里面放的元素和样式是不受限制的,比如html这样写还是能够正确计算的。
1 | html复制代码<div class="ellipsis box"> |
创建一个div来获取模拟宽度
我们可以还可以通过创建一个几乎相同的div来获取没有overflow:hidden
时元素的实际宽度。
1 | html复制代码<div class="ellipsis box"> |
1 | js复制代码const checkEllipsis = () => { |
当box元素里面存在多个dom元素的时候,还得进行一个递归创建dom,或者也可以试试cloneNode(true)
来试试克隆。
创建一个block元素来包裹inline元素
这种方法从acro design vue
中学到的,应该是最简单的办法。要点就是外层一定是block元素,内层是inline元素
1 | html复制代码<div class="ellipsis box"> |
通过上面对css和html做的处理,我们可以实现让box元素里面的文字进行ellipisis,同时由于并没有 对span.content
进行任何overflow的处理,所以该 span 的offsetWidth还是保持不变。
1 | js复制代码const checkEllipsis = () => { |
同样,只要满足外层元素是block,内层元素是inline的话,里面的dom元素其实是随便放的
1 | html复制代码<div class="ellipsis box"> |
方法比较
- 性能(个人主观判断)3>1>2
- 省心程度(个人主观判断):1>3>2
- 精确度(个人主观判断):3种方法精确度几乎相同,如果硬要比较我觉得是3>1>2
之后我在看看其他组件库有什么好的方法,然后再补充上来,前端总是在做这些很小很小的点,哈哈。
本文转载自: 掘金