项目中经常会遇到这样一个问题或需求:一段文本A,如果A较短则全部显示;如果A比较长,则显示省略号,同时鼠标hover会有提示,类似el-tooltip(或者单独写提示框)。
遇到这类问题或需求,如何处理???
一般的处理方案有(Vue、elementUI为例):
1、通过获判断文本A的长度,控制提示框的显示/隐藏,代码如下:
<template>
<div id="demo">
<el-tooltip
v-if="text.length > 5"
class="item"
effect="dark"
:content="text"
placement="top"
>
<span>{{ text }}</span>
</el-tooltip>
<span v-else>{{ text }}</span>
</div>
</template>
<script>
export default {
name: 'index',
components: {},
data() {
return {
text: '提示文字提',
}
},
methods: {},
}
</script>
<style scoped lang="scss">
#demo {
width: 100%;
span {
width: 100px;
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
}
}
</style>
以上代码会出现这么一个问题:如果全是汉字,显示正常;假如包含了数字、英文字母或符号,就会有问题。把text换成英文、数字或字符,没有显示省略号,但是鼠标hover后还会有文字提示。
2、第二种处理方案可以说是上面的升级版:省略号不用样式控制,手动添加(如通过过滤器处理)。代码如下:
<template>
<div id="demo">
<el-tooltip
v-if="text.length > 5"
class="item"
effect="dark"
:content="text"
placement="top"
>
<span>{{ text | textHandle(text) }}</span>
</el-tooltip>
<span v-else>{{ text }}</span>
</div>
</template>
<script>
export default {
name: 'index',
components: {},
data() {
return {
text: '提示文字提示文字',
}
},
filters: {
textHandle: function(val) {
let textNew = val
if (val.length > 5) {
textNew = val.slice(0, 5) + '…'
}
return textNew
},
},
methods: {},
}
</script>
<style scoped lang="scss">
#demo {
width: 100%;
span {
width: 100px;
display: inline-block;
}
}
</style>
这种处理方案,避免了第一种比较严重的问题。看似完美,但是还有瑕疵:虽然做到了只有在省略号出现的情况,鼠标hover才会出现提示框。但是汉字、数字、英文或符号“出现省略号的临界点的文本长度不同”。
例如,上面代码的汉字出现省略号的临界点是6个汉字,文本长度正好填满span标签(width为100px);但数字、英文或符号,虽然临界点也是6个,文本长度却低于span标签设置的固定宽度。
这种方案的问题:汉字、数字、英文字母和符号等出现省略号的文本长度不能保持统一。
以上两种方案都出现问题根本原因:一个汉字占用2个字符;一个数字、一个英文字母或一个符号等占用1个字符。
3、第三种处理方案:
对汉字、数字、英文字母和符号等处理成统一的形式(比如依汉字为标准,对数字、英文字母和符号等进行对应的转换)。这种方式能够彻底解决问题。但有点繁琐,不推荐。
> 终极方案:
个人理解:以上方案都是从字节在浏览器中渲染之前入手的,但是字节编码形式有多种,导致多种问题产生。虽然也能彻底解决,但不是最优的解决方案。
建议方案:从字节在浏览器中渲染后入手:拿到最终的文本宽度widthA,外层包裹的壳为固定宽度(或区间宽度)widthB,代码如下:
.vue文件中使用封装好的组件yjl-ellipsis(组件已在全局注册)
<template>
<div id="structure">
<yjl-ellipsis
:placement="placement"
:outerShellWidth="width"
:contentText="text"
></yjl-ellipsis>
</div>
</template>
<script>
export default {
name: 'structure',
components: {},
data() {
return {
placement: 'top',
width: 288,
text: '展示多行文本或者是设置文本内容的格式',
}
},
methods: {},
}
</script>
<style scoped lang="scss">
#structure {
width: 100%;
}
</style>
封装好的组件yjl-ellipsis代码(全局注册):
<template>
<div id="yjlEllipsis">
<div class="contentCls" :style="{ width: width }">
<el-tooltip
class="item"
effect="dark"
:disabled="isElTooltipShow"
:content="contentText"
:placement="placement"
>
<span @mouseenter="hanldeElTooltip">
{{ contentText }}
</span>
</el-tooltip>
</div>
</div>
</template>
<script>
export default {
name: 'yjlEllipsis',
props: {
placement: {
// Tooltip 出现位置。位置汇总:top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end
type: String,
default: 'top',
},
outerShellWidth: {
// Tooltip 外层壳的宽度,default自定义设置
type: Number,
default: 1,
},
contentText: {
// 文本内容
type: String,
default: '',
},
},
computed: {
width() {
// Tooltip 外层壳宽度自动填充px
return this.outerShellWidth + 'px'
},
},
data() {
return {
isElTooltipShow: true, // Tooltip 是否可用
}
},
mounted() {},
methods: {
hanldeElTooltip(val) {
if (val.target.offsetWidth > this.outerShellWidth) {
// 作比较:文本实际的宽度与外层壳的宽度
this.isElTooltipShow = false
}
},
},
}
</script>
<style scoped lang="scss">
#yjlEllipsis {
width: 100%;
.contentCls {
// 外层壳已做单行文本溢出显示省略号处理
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
}
}
</style>
处理思路:
1、外壳B,为固定宽度(或区间宽度)widthB,做单行文本溢出显示省略号处理,内嵌文本A;
2、文本A,通过mouseenter事件(hanldeElTooltip)获取文本的实际宽度widthA;
3、widthA与widthB做比较,然后控制el-tooltip的disabled属性(Tooltip 是否可用),最终实现效果。
备注:
1、组件yjl-ellipsis暂时接收3个属性placement(Tooltip 出现位置)
、outerShellWidth(外壳B宽度)
、contentText(文本内容)
;
2、全局注册组件未在本文中体现。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。