自定义vue指令,实现el-tooltip仅在文字溢出时显示,文字未溢出则不显示,复制即可使用

这篇具有很好参考价值的文章主要介绍了自定义vue指令,实现el-tooltip仅在文字溢出时显示,文字未溢出则不显示,复制即可使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、写在开头

在项目里遇到了这种需求,想到el-table里的show-overflow-tooltip属性就有这种效果,在参考了一些网上的文章以及show-overflow-tooltip跟el-tooltip的源码后,觉得使用自定义指令的方式来实现这个需求会很方便,于是便有了以下代码


二、自定义指令代码

1、创建一个js文件,复制粘贴以下代码即可使用,无需改动

import Vue from 'vue'
import debounce from 'throttle-debounce/debounce'
import { Tooltip } from 'element-ui'
Vue.use(Tooltip)

/**
 * 指令功能:元素内容溢出隐藏时悬浮tooltip展示详细内容,元素内容未溢出时不展示
 * 基于element-table的show-overflow-tooltip原理与el-tooltip的功能实现
 * 使用方式:
 *   <div v-overflow-tooltip>这是一段会溢出的文本内容</div>
 *
 * 指令也可传递参数,参数内容为el-tooltip的参数配置:
 *   <div v-overflow-tooltip="{content:'啦啦啦啦~~~'}">这是一段会溢出的文本内容</div>
 * */

/**
 * tooltipVM —— el-tooltip的VNode实例
 * tooltipContent —— 默认提示文本内容
 * props —— el-tooltip的配置参数
 * ctx —— 命名空间
 * activateTooltip —— el-tooltip展开的防抖延迟,默认50ms
 * */
let tooltipContent
let props
const ctx = '@@store'
// 创建一个Vue实例并渲染为真实DOM,内有一个空的el-tooltip组件
const vm = new Vue({
  render (h) {
    return (<Tooltip ref="customToolTipRef" content={ tooltipContent } { ...{ props } }></Tooltip>)
  }
}).$mount()
const tooltipVM = vm.$refs.customToolTipRef
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.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]
  }
})

2、使用方法

2.1. 默认无参数用法

没有传递值给指令的时候,将使用el-tooltip的默认配置,提示内容默认显示指令绑定元素的文本内容

<el-input v-model="value" placeholder="请输入内容" style="width: 200px; margin-bottom: 25px"></el-input>

<div v-overflow-tooltip class="overflow">{{ value }}</div>
自定义vue指令,实现el-tooltip仅在文字溢出时显示,文字未溢出则不显示,复制即可使用

默认效果

2.2. 自定义传递参数用法

参数内容其实就是el-tooltip官方定义可以传递的配置参数,我们可以自定义内容、主题、显示位置等

<el-input v-model="value" placeholder="请输入内容" style="width: 200px; margin-bottom: 25px"></el-input>

<div v-overflow-tooltip="{content:'这是通过content自定义的溢出显示内容',effect:'light'}" class="overflow">{{ value }}</div>
自定义vue指令,实现el-tooltip仅在文字溢出时显示,文字未溢出则不显示,复制即可使用

自定义参数效果

三、实现原理简述

不了解自定义指令的小伙伴可以看一下我在文末分享的链接。

最开始我们需要创建一个tooltip的vue实例,以及其他的一些空变量为后续内容做准备。此处为了方便,vue实例中使用了JSX语法,大家可以根据需求更换为h函数(createElement)的写法。

声明了一个overflowHandler方法,此方法用于在指令的inserted与componentUpdated生命周期执行,该方法内部获取了元素的文本内容与配置参数,并判断文本是否溢出,根据是否溢出来进行绑定或者移除鼠标事件。

判断文本是否溢出最简单的方式就是比较元素的scrollWidth是否大于offsetWidth,但是elementUI并不是这么判断的,他们是用range对象去进行判断,这里我们也这么用,将绑定元素的开头设定为range对象的起始点,再将绑定元素的末尾设置为range对象的结束点(绑定元素的末尾指该元素的所有直接子节点的总数,注意:是直接子节点childNodes!!!不是直接子元素children!!!),关于range对象的使用我会在文末贴上链接。

自定义指令的生命周期中,在最初的bind周期里,我们只做一件事,也是最重要的一件,在绑定的DOM元素上开辟一个新的空间,存储我们需要的内容默认文本,配置参数,鼠标移入溢出事件。

关于鼠标事件内的逻辑,除了handleMouseEnter中最开始的三句,意为获取参数后重新渲染一次tooltip组件,其他部分都是照搬elementUI的源码,用于展开与收起tooltip。

inserted与componentUpdated生命周期中执行我们之前声明的overflowHandler方法。

unbind生命周期中删除我们为当前DOM所开辟的新空间。

四、存在问题以及个人疑问

1、存在问题

这个指令虽然能用,但还是存在一些问题的,最明显的有两点。

  • 绑定元素层级只能有一级,不能有多级,比如有时候想给el-input也实现溢出提示的效果,该自定义指令不生效。

  • 无法判断多行文本换行时的溢出隐藏,比如有时我们除了限制文本单行溢出隐藏外,还会设置2行、3行等溢出隐藏,此时指令不生效,因为自定义指令中的判断仅能判断单行文本是否溢出。

  • .........

该指令还有进一步优化的空间,但是这里我个人觉得投入产出比太小没必要,各位可以根据自己的需求进行优化,也欢迎各位将自己发现的问题跟优化方案贴出。

2、个人疑问

我在获取到指令传递过来的对象binding.value时,将他重新赋给了变量props,之后又在JSX里进行了传递,写法是{...{ props }},但是按照JSX的传递多个参数的写法,这里不是应该写{...props}就可以了了吗,为什么我这么写的话,el-tooltip一直接收不到传递过来的值呢?我很好奇,而且这里我还必须给变量命名为props,换个别的名字后组件也会接收不到值,查了半天也没解决这个疑问😥,各位大佬能帮我解惑下吗😳

五、参考文章

  • element table组件的show-overflow-tooltip属性的实现原理:https://wangzl.blog.csdn.net/article/details/122353237

  • el-table 组件源码:https://github.com/ElemeFE/element/blob/dev/packages/table/src/table-body.js

  • el-tooltip 组件源码:https://github.com/ElemeFE/element/blob/dev/packages/tooltip/src/main.js

  • Range对象的使用:https://developer.mozilla.org/zh-CN/docs/Web/API/Range

  • Vue自定义指令:https://v2.cn.vuejs.org/v2/guide/custom-directive.html


如若转载,请注明出处,谢谢😄😄😄文章来源地址https://www.toymoban.com/news/detail-444061.html

到了这里,关于自定义vue指令,实现el-tooltip仅在文字溢出时显示,文字未溢出则不显示,复制即可使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3中如何使用el-tooltip中的插槽达到换行效果

    el-tooltip的content属性中的内容可以使用插槽来替换 话不多说,直接上代码 最后放上效果对比图,如果觉得有帮到你,可以给我一个赞吗😜 没换行前的效果 换行后的效果

    2024年02月10日
    浏览(54)
  • 基于Vue2.0仿Element UI的el-tooltip实现一个气泡框组件,支持多数据类型的显示和内容为空时不显示气泡框

    场景:因为有个需求就是鼠标经过可多选的 el-select 选择器时,需要有个气泡框显示已选的内容,其实 el-tooltip 气泡框可以满足需求,就是用 el-tooltip 气泡框来包裹 el-select 选择器,但是当选择器一个也没选中,即内容为空时不应该也显示气泡框,有点影响美观。应该就是若内

    2024年02月13日
    浏览(48)
  • Vue3 el-tooltip 根据内容控制宽度大小换行和并且内容太短不显示

    tooltip 根据内容自动换行 如果内容超出显示省略号显示,不超出不显示 tooltip 组件 使用

    2024年02月09日
    浏览(46)
  • el-tooltip 修改宽度

    使用 popper-class 为 Tooltip 的 popper 添加类名 在当前组件新建一个 style ,不要写 scoped ,这里的样式会应用到全局,所以 class 命名一定要保证不要和全局别的类名重复 当然,也可以用 slot ,在 slot 中自定义类名

    2024年02月16日
    浏览(66)
  • el-tooltip的使用(根据条件控制显示)

    一、列表型 代码如下: 效果展示: 二、树状图型 代码如下: 效果展示: 注意:均要设置所设选择器的样式 附JSON数据

    2024年02月11日
    浏览(40)
  • eltable el-tooltip__popper 换行、字体、颜色等调整

    show-overflow-tooltip属性 element-ui表格 默认情况下若内容过多会折行显示,若需要单行显示可以使用show-overflow-tooltip属性,它接受一个Boolean,为true时多余的内容会在 hover 时以 tooltip 的形式显示出来。 默认情况 element-ui表格 show-overflow-tooltip=\\\"true\\\",鼠标移上去会显示如下图的样子

    2024年02月07日
    浏览(49)
  • el-tab-pane 和el-tooltip及el-tree 组合使用

    这里主要是在el-tab-pane中的label属性不给赋值,单独写在el-tooltip中,使用span去写当前的名称,就可以实现鼠标放上去,浮现树的效果。

    2024年02月13日
    浏览(41)
  • element ui 中在el-table内,当内容超过多少行时,显示el-tooltip

    最近来了一个需求,在一个el-table里边的某一列渲染一个 ‘介绍’ 的内容,由于内容过多,全部展示显示的不是很美观,所以就给定了个需求让超出两行后显示省略号,并在鼠标移上去之后显示全部内容。 我首先想到的就是使用el-tooltip来实现,但是在使用过程中试了很多方

    2024年02月03日
    浏览(48)
  • [element-ui] el-table表格头添加图标-鼠标移入显示el-tooltip提示信息

    只是单纯的想在table中添加图标和tooltip 在el-table-column中绑定:render-header=“renderPrice” (此方法无法使tooltip换行) 方法二、 使用组件插槽,elementui已封装好 elementUI表格头添加图标-鼠标移入显示el-tooltip提示信息

    2024年02月11日
    浏览(50)
  • 【Element UI】解决el-tooltip组件在鼠标快速移动场景下出现的残影问题

    当我们把el-tooltip组件直接拿来和el-table组件使用的时候,鼠标上下快速移动会出现如图残影和渐变消失的问题 如下图: 所以我们去看一下官网 我们这时候试一试将 transition 属性设置为空 代码如下: 发现渐变消失是解决了但是并没有解决鼠标快速移动产生残影的问题 最终代

    2024年02月19日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包