项目中常常会遇到这样一个问题或需求:一段文本A,若是A较短则所有显示;若是A比较长,则显示省略号,同时鼠标hover会有提示,相似el-tooltip(或者单独写提示框)。css
遇到这类问题或需求,如何处理???
通常的处理方案有(Vue、elementUI为例):
一、经过获判断文本A的长度,控制提示框的显示/隐藏,代码以下:vue
<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后还会有文字提示。浏览器
二、第二种处理方案能够说是上面的升级版:省略号不用样式控制,手动添加(如经过过滤器处理)。代码以下:this
<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标签设置的固定宽度。
这种方案的问题:汉字、数字、英文字母和符号等出现省略号的文本长度不能保持统一。spa
以上两种方案都出现问题根本缘由:一个汉字占用2个字符;一个数字、一个英文字母或一个符号等占用1个字符。code
三、第三种处理方案:component
对汉字、数字、英文字母和符号等处理成统一的形式(好比依汉字为标准,对数字、英文字母和符号等进行对应的转换)。这种方式可以完全解决问题。但有点繁琐,不推荐。事件
我的理解:以上方案都是从字节在浏览器中渲染以前入手的,可是字节编码形式有多种,致使多种问题产生。虽然也能完全解决,但不是最优的解决方案。ip
建议方案:从字节在浏览器中渲染后入手:拿到最终的文本宽度widthA,外层包裹的壳为固定宽度(或区间宽度)widtB,代码以下:
.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>
处理思路:
一、外壳B,为固定宽度(或区间宽度)widthB,作单行文本溢出显示省略号处理,内嵌文本A;
二、文本A,经过mouseenter事件(hanldeElTooltip)获取文本的实际宽度widthA;
三、widthA与widthB作比较,而后控制el-tooltip的disabled属性(Tooltip 是否可用),最终实现效果。
备注:
一、组件yjl-ellipsis暂时接收3个属性placement(Tooltip 出现位置)
、outerShellWidth(外壳B宽度)
、contentText(文本内容)
;二、全局注册组件未在本文中体现。