一尘子、道法自然、博客园、前端

文本溢出时,悬浮显示,使用自定义指令

单行溢出代码
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
多行溢出代码
overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; word-break: break-all; -webkit-box-orient: vertical;

JS文件

import Vue from 'vue';
import { Tooltip } from 'element-ui';
Vue.use(Tooltip);
let tooltipContent
let props
const ctx = '@@store'
// 创建一个Vue实例并渲染为真实DOM,内有一个空的el-tooltip组件
const vm = new Vue({
  render (h) {
    return (<Tooltip ref="customToolTipRef" popper-class="item-popper" placement="top" content={ tooltipContent } { ...{ props } }></Tooltip>)
  }
}).$mount()
const tooltipVM = vm.$refs.customToolTipRef

import debounce from 'throttle-debounce/debounce';
const activateTooltip = debounce(50, tooltipVM => tooltipVM.handleShowPopper());



const overflowHandler = (el, binding, vnode) => {
  
  // 获取元素文本内容,作为el-tooltip的默认content进行展示
  el[ctx].tooltipContent = el.innerText || el.textContent
  // 获取通过指令接收的绑定值
  el[ctx].props = { ...binding.value }
  const computedStyle = getComputedStyle(el)
  // 使用range对象判断文本是否有溢出,优先考虑使用range对象, 因为 scrollWidth 属性在火狐浏览器 v32 版本中有 bug。当元素的 CSS 属性中使用了 text-overflow: ellipsis 和 box-sizing: border-box 时获取到的 scrollWidth 的值会比真实值偏小
  const range = document.createRange()
  range.setStart(el, 0)
  range.setEnd(el, el.childNodes.length)
  const rangeDOM = range.getBoundingClientRect()
  const padding = parseInt(computedStyle.paddingLeft.replace('px', '')) + parseInt(computedStyle.paddingRight.replace('px', ''))
  const rangeWidth = Math.round(rangeDOM.width)
 
  if (rangeWidth + padding > el.offsetWidth || el.scrollWidth > el.offsetWidth || el.scrollHeight > el.offsetHeight) {
    // 文本溢出了,绑定鼠标事件
    el.addEventListener('mouseenter', el[ctx].handleMouseEnter)
    el.addEventListener('mouseleave', el[ctx].handleMouseLeave)
  } else {
    // 文本未溢出,移除鼠标事件
    el.removeEventListener('mouseenter', el[ctx].handleMouseEnter)
    el.removeEventListener('mouseleave', el[ctx].handleMouseLeave)
  }
}

Vue.directive('overflowTooltip', {
    // 只调用一次,指令第一次绑定到元素时调用。在这里进行一次初始化设置,初始化鼠标事件,控制el-tooltip的展开与收起
  bind: function (el, binding, vnode) {
    el[ctx] = {
      tooltipContent: '',
      props: {},
      handleMouseEnter: () => {
        
        // 展开el-tooltip方法,将el-tooltip的引用元素指向当前绑定节点,然后执行展开逻辑
        tooltipContent = el[ctx].tooltipContent
        props = el[ctx].props
        vm.$forceUpdate()
        tooltipVM.referenceElm = el
        tooltipVM.$refs.popper && (tooltipVM.$refs.popper.style.display = 'none')
        tooltipVM.doDestroy()
        tooltipVM.setExpectedState(true)
        activateTooltip(tooltipVM)
      },
      handleMouseLeave: () => {
        // 关闭el-tooltip方法,销毁内部popperJS的实例后走关闭逻辑
        tooltipVM.doDestroy()
        tooltipVM.setExpectedState(false)
        tooltipVM.handleClosePopper()
      }
    }
  },
  inserted: overflowHandler,
  componentUpdated: overflowHandler,
  unbind (el) {
    delete el[ctx]
  }

})

main.js引入
import '@/utils/tooltip'
设置溢出后,悬浮显示
<div class="item-title" v-overflow-tooltip="{content:'筹备召开只调用一次,指令第一次绑定到元素时调用。在这里进行一次初始化设置'}">筹备召开只调用一次,指令第一次绑定到元素时调用。在这里进行一次初始化设置</div>
参考网址
https://juejin.cn/post/7411160922645446690

posted @ 2024-09-13 19:57  一尘子!  阅读(29)  评论(0编辑  收藏  举报
Live2D
返回顶端