el-tooltip与文本省略号实现精确同步(有省略号就有文本提示,无省略号无文本提示)

项目中经常会遇到这样一个问题或需求:一段文本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,外层包裹的壳为固定宽度(或区间宽度)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>

处理思路:
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、全局注册组件未在本文中体现。

原文链接:segmentfault.com

上一篇:Vue-router 路由
下一篇:SVG在Vue中如何引入?如何做到懒人引入?

相关推荐

官方社区

扫码加入 JavaScript 社区