項目中常常會遇到這樣一個問題或需求:一段文本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(文本內容)
;二、全局註冊組件未在本文中體現。