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(文本内容);二、全局注册组件未在本文中体现。

相关文章
相关标签/搜索