el-tooltip與文本省略號實現精確同步(有省略號就有文本提示,無省略號無文本提示)

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

相關文章
相關標籤/搜索