前言
在业务开发中,总是会碰到一行文字过长时,超出了内容
<div style="width: 100px; border: 1px solid #ccc">This is some long text that will not fit in the box</div>
一般的处理方法是通过样式来进行控制
text-overflow:ellipsis;
white-space:nowrap;
overflow:hidden;
但随之而来碰到的问题是,如何显示超出部分的文字,实现也很简单,使用el-tooltip组件进行一层包装
<el-tooltip
class="item"
effect="dark"
content="This is some long text that will not fit in the box" placement="top-start">
<div style="width: 100px; border: 1px solid #ccc">This is some long text that will not fit in the box</div>
</el-tooltip>
但如果每次进行如此操作显得不够优雅,于是才有了下面的思路
封装组件
在开始之前首先需要了解scrollWidth、offsetWidth、clientWidth的关系
clientWidth = padding + content
offsetWidth = padding + content + border
scrollWidth = padding + content(包含溢出部分)
正常情况下(内容不溢出并且没有border)offsetWidth === scrollWidth
所以可以通过offsetWidth < scrollWidth来进行判断
首先我们期望正常外层写法类似于
<custom-text>
超长文字
</custom-text>
所以可以通过this.$slots.default获取这个slots,为了统一进行ref获取,我们在外层包装一层span
const content = (
<span
class="content"
id="saveRef"
ref="saveRef"
>
{this.$slots.default}
</span>
);
在组件挂载的时候进行长度的判断来进行判断是否需要显示提示
data() {
return {
hasToolTip: false
}
},
mounted() {
this.updateToolTip();
},
methods: {
updateToolTip() {
this.hasToolTip =
this.$refs['saveRef'].offsetWidth < this.$refs['saveRef'].scrollWidth;
}
}
如果存在文字过长,一行超出的情况
<el-tooltip
content={text}
class="item"
effect="dark"
placement="top-start"
>
{content}
</el-tooltip>
这里有两种选择来进行提示内容的设置
- 通过获取content中的innerHTML slots在vue中的表示类似于这样
const slots = {
default: [VNode]
}
但也可能外层传过来的时候本来就包装了span,此时slots类似于这样
const slots = {
default: [{
...
children: [VNode]
}]
}
所以我们可以这样进行获取
const text = this.$slots.default[0].text || this.$slots.default[0].children[0].text
- 通过外部传参进行获取
<custom-text :text="text">
content
</custom-text>
props: {
text: {
type: String,
default: ''
}
}
const text = this.text;
PS: 为了避免不必要的计算比较,可以将计算是否需要tooltip放在鼠标移上去的时候
最终可以这样表示
render() {
const content = (
<span
class="content"
id="saveRef"
ref="saveRef"
onMouseover={this.updateToolTip}
>
{this.$slots.default}
</span>
);
const text =
this.$slots.default[0].text ||
this.$slots.default[0].children[0].text ||
this.text;
return this.hasToolTip ? (
<el-tooltip
content={text}
class="item"
effect="dark"
placement="top-start"
>
{content}
</el-tooltip>
) : (
content
);
}
总结
总的来说,还是需要掌握基础,了解了基础的一些知识才能够应对更加复杂的场景,有更多解决办法的思路。前端学习的路还很长,继续在学习优雅的路上前进。写这篇文章的初衷,一方面记忆自己的思路,另一方面分享给大家一起学习,如果写的不正确的地方,还希望得到各位大佬的指正,谢谢!