vue项目单行文本溢出处理

前言

一般最常见的详情信息展示页面,都需要处理文字溢出的情况。当然也可以用原生的“title属性”,但是太low!

 

背景

多行文本每个项目处理的方式不一样,这里单独介绍单行文本溢出的场景:
  1)当文字溢出时,超出部分显示三个点,el-tooltip组件悬浮显示全部文字;

  2)文字未超出时,正常显示,不显示悬浮窗

 

技术栈

vue项目使用element-ui框架

 

实现

 

思路一:使用render函数

本来想着只是单纯的渲染组件,所以就用vue的render函数写,但是写着很快发现不对劲——因为需要文字全部渲染后才知道文字是否溢出,所以只能想别的方法

<script>
import Tooltip from 'element-ui/lib/tooltip.js'
export default {
  components:{ Tooltip },
  props: { text: String },
  data () {
    return {
      manual: true
    }
  },
  methods: {
    render (h) {
      const { text } = this.$props
      const Text = <div>{text}</div>

      const manual = this.textRange(h(Text, text))
      const wrapStyle = {
        width: '100%'
      }

      return <div style={wrapStyle}>
        <div>{text + ' ' + wrapStyle}</div>
        <Tooltip content={text} manual={manual}>
          {Text}1900111
        </Tooltip>
      </div>
    }
  }
}
</script>

 

思路二:使用vue自定义指令

既然无法在渲染前获取Dom,那么在渲染的时候获取Dom总可以了吧!但是事实打脸~,得出结论:指令获取的Dom还是虚拟的,也就是还是渲染前虚拟Dom。

<template>
  <div class="ellipsis" v-title>
    <slot></slot>
  </div>
</template>

<script>
import Tooltip from 'element-ui/lib/tooltip.js'
function showOverflowHiddenText (el, value) {
  if (el.offsetWidth < el.scrollWidth) {
  if (isOver) {
    let title = value
    if (!value) {
      var re1 = new RegExp('<.+?>', 'g')
      title = el.innerHTML.replace(re1, '')
    }
    el.setAttribute('title', title)
  }
}
export default {
  components: { Tooltip },
  props: { text: String },
  directives: {
  title: {
      inserted: (el, binding, vnode) => {
        showOverflowHiddenText(el, binding.value ? binding.value.title : '')
      },
      update: (el, binding, vnode) => {
        showOverflowHiddenText(el, binding.value ? binding.value.title : '')
      }
    }
  }
}
</script>

 

思路三:添加鼠标移入事件(最终思路)

总结思路一的失败教训,本着先渲染才知道是否溢出的原则,给文本元素添加鼠标移入事件来判断溢出才显示浮窗

 

利用tooltip组件的“manual”属性

参数 说明 类型 可选值 默认值
manual 手动控制模式,设置为 true 后,mouseenter 和 mouseleave 事件将不会生效 Boolean false

 

<template>
  <div :class="['text-ellipsis',`text-ellipsis_${guid()}`]">
    <tooltip :content="text" placement="top" :manual="manual">
      <!-- 必须给文本元素进行溢出处理 -->
      <div class="ellipsis" @mouseenter="handleMouse">{{text}}</div>
    </tooltip>
  </div>
</template>
<script>
import Tooltip from 'element-ui/lib/tooltip.js'
export default {
  name: 'TextEllispis',
  components: { Tooltip },
  props: { text: String },
  data () {
    return {
      manual: true
    }
  },
  methods: {                                  
    guid () {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        let r = Math.random() * 16 | 0
        let v = c === 'x' ? r : (r & 0x3 | 0x8)
        return v.toString(16)
      })
    },
    handleMouse (e) /* 鼠标移入事件 */ {
      const { target: { scrollWidth, offsetWidth } } = e
      this.manual = scrollWidth <= offsetWidth
    }
  }
}
</script>

 

判断文本是否溢出还有另外一种方法

handleMouse(e) {
  const textRange => (el) {
    const textContent = el
    const targetW = textContent.getBoundingClientRect().width
    const range = document.createRange()
    range.setStart(textContent, 0)
    range.setEnd(textContent, textContent.childNodes.length)
    const rangeWidth = range.getBoundingClientRect().width
    return rangeWidth > targetW
  }
  this.manual = !textRange(e)
}

 

样式部分

查看样式代码
<style lang="less" scoped>
.ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  word-wrap: break-word;
}
.text-ellipsis {
  width: 100%;
  .ellipsis;
}
</style>

 

posted @ 2022-08-15 17:28  丿流水  阅读(1081)  评论(0)    收藏  举报