基于 ElementUI 封装的 TextEllipsis
做项目中文本溢出显示省略号是一个非常常见的功能, 一般做法都是增加 css
样式并且鼠标悬浮后显示全部内容, 但有时候明明没有溢出, 悬浮也会显示内容, 所以我们需要做一点处理
这里我们主要使用 el-tooltip
这个组件来实现这个功能
# 封装思路:
- 通过
content
传入文本 - 通过
css
实现溢出显示省略号的样式 - 鼠标悬浮后, 判断
scrollWidth
是否超过offsetWidth
, 如果超过, 显示tooltip
, 否则设置disabled
由于比较简单, 直接上代码了:
# 代码
<template>
<el-tooltip class="text-ellipsis" v-bind="$attrs" :disabled="disabled" :content="content">
<div @mouseenter.stop="handleMouseEnter">
{{ content }}
</div>
</el-tooltip>
</template>
<script>
export default {
name: 'TextEllipsis',
props: {
content: {
type: String,
default: ''
}
},
data() {
return {
disabled: true
}
},
methods: {
handleMouseEnter(e) {
const { scrollWidth, offsetWidth } = e.target
this.disabled = scrollWidth <= offsetWidth
}
}
}
</script>
<style lang="less" scoped>
.text-ellipsis {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 扩展 - 多行
最近遇到需要多行溢出显示省略号的需求, 而咱们这个只支持单行, 所以需要扩展一下
css
样式比较好搞定:
.text-ellipsis {
width: 100%;
overflow: hidden;
display: -webkit-box;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
}
2
3
4
5
6
7
-webkit-line-clamp
这个属性需要通过 props
接收并在 div
中设置:
<div :style="{ '-webkit-line-clamp': lineClamp }" @mouseenter.stop="handleMouseEnter">
{{ content }}
</div>
2
3
而 js
就比较麻烦了, 在群里问了大佬一下, 貌似没有哪个方法可以获取是否出现省略号, 都需要自己计算来获取
而且都比较麻烦, 需要判断 padding
border
等尺寸, 而咱们一般使用比较简单, 没那么复杂, 所以就参照以前的改改吧
此时就需要用 height
来代替 width
计算是否出现省略号:
handleMouseEnter({ target }) {
const { scrollHeight, offsetHeight } = target
this.disabled = scrollHeight <= offsetHeight
}
2
3
4
本来测试的是没问题的, 没想到项目实际中竟然出现 scrollHeight
比 offsetHeight
多 1px
的情况, 导致明明没有出现省略号, 鼠标悬浮上去的时候会显示 tooltip
经过一番研究后发现如果出现省略号, 那么 scrollHeight
的高度至少比 offsetHeight
高一行, 那么能不能按照这个逻辑来计算呢?
handleMouseEnter({ target }) {
const { scrollHeight, offsetHeight } = target
// 这里不能再用 <=
this.disabled = scrollHeight - offsetHeight < offsetHeight / this.lineClamp
}
2
3
4
5
再次测试后, 发现如果增加 border
, scrollHeight
的高度比 offsetHeight
高一行时, 计算仍有误, 这是因为 offsetHeight
有 border
的宽度, 而 scrollHeight
并没有, 所以还是用 clientHeight
吧
handleMouseEnter({ target }) {
const { scrollHeight, clientHeight } = target
// 这里不能再用 <=
this.disabled = scrollHeight - clientHeight < clientHeight / this.lineClamp
}
2
3
4
5
# 问题
# padding 会有影响
如图所示, 这里设置 padding: 50px
, 可以看到虽然出现了省略号, 但第四行并没有被隐藏, 而且计算又有误了, 只有当出现第五行的时候, 计算才正确
这个 bug
目前就不打算解决了, 毕竟 chrome
还没有解决呢! 🐶
其实这个说难很难, 说简单也简单!
在外面包裹一层不就可以了吗? 外层控制位置等样式, 内层控制多行省略号即可
<el-tooltip
class="text-ellipsis"
v-bind="$attrs"
:disabled="disabled"
:content="content"
:open-delay="openDelay"
>
<div>
<div
class="text-ellipsis-content"
:style="{ '-webkit-line-clamp': lineClamp }"
@mouseenter.stop="handleMouseEnter"
>
{{ content }}
</div>
</div>
</el-tooltip>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text-ellipsis {
width: 100%;
&-content {
display: -webkit-box;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal; // 使用默认值, 防止继承属性的时候高度计算有误
-webkit-box-orient: vertical;
}
}
2
3
4
5
6
7
8
9
10
11