vue根据文字动态判断溢出...鼠标悬停显示el-tooltip展示

使用自定义el- tooltip 组件

定义

Tooltip是一种小型弹出框,它显示有关特定页面元素的信息,例如按钮、链接或图标。Tooltip通常以半透明的气泡形式呈现,并出现在页面元素的旁边或下方。

它可以改善用户体验,使用户更容易理解页面元素的功能和意图。用户可以通过将鼠标悬停在页面元素上来快速了解有关该元素的信息,而无需离开当前页面或浏览其他页面。

定位问题,很重要,top topLeft topRight bottom bottomLeft bottomRight left right,tooltip可以出现在不同的位置
采用默认插槽的方式,将需要tooltip的内容放置
通过父组件传入的visible进行手动控制tooltip的显现和隐藏
可以自定义tooltip背景色,如果自定义了,文字为白色

创建tooltip组件

/assets/directive/tooltip.js

在全局main.js引入组件

import tooltip from '@/assets/directive/tooltip.js'
Vue.directive('tooltip', tooltip)

组件代码(按需修改)

import {  getLanguage } from '@/assets/language/langs'
export default {
    // 指令所在组件的 VNode 及其子 VNode 全部更新后调用
    
      bind (el) {
      // componentUpdated (el) {
      //componentUpdated 不能初始响应//修改为bind (el, binding) {
    //   console.log(...arguments);
      /* 第1步:先要创建一个容器`span`去获取文本的宽度 */
      // 获取当前元素的style
      const curStyle = window.getComputedStyle(el, '');

      // 创建一个容器来记录文字的width
        const textSpan = document.createElement('span');
        // 设置新容器的字体样式,确保与当前需要隐藏的样式相同
        textSpan.style.fontSize = curStyle.fontSize;
        textSpan.style.fontWeight = curStyle.fontWeight;
        textSpan.style.fontFamily = curStyle.fontFamily;
        // 将容器插入body,如果不插入,offsetWidth为0
       
        document.body.appendChild(textSpan);
        // 设置新容器的文字
        const arr = el.innerText.split("  ");
        textSpan.innerHTML = arr[0];
        // console.log(textSpan.offsetWidth,'-------设el')
        var menu = document.getElementById('scenesSub');
        var uls = menu.getElementsByTagName('ul');
        var lis = menu.getElementsByTagName('li');
        var htmlWidth = document.documentElement.offsetWidth;

      // 如果字体元素大于当前元素长度,则需要隐藏
      /* 第2步:用获取到的宽跟`元素长度`的宽进行对比,如果文本字体大于当前`元素长度`元素的宽度,则需要title提示
       * 第3步:监听`el`的`onmouseenter`以及`onmouseleave`的鼠标移入移出事件
       */ 
      var jmz = {};
      jmz.GetLength = function(str) {
          ///<summary>获得字符串实际长度,中文2,英文1</summary>
          ///<param name="str">要获得长度的字符串</param>
          var realLength = 0, len = str.length, charCode = -1;
          for (var i = 0; i < len; i++) {
              charCode = str.charCodeAt(i);
              if (charCode >= 0 && charCode <= 128) realLength += 1;
              else realLength += 2;
          }
          return realLength;
      };
      
      
      //鼠标移入
      el.onmouseenter = (e) => {
        // console.log(e);
        var currLang=getLanguage()
        var innerlength= jmz.GetLength(el.innerText)
        // console.log(innerlength, el.innerText,currLang,'==========el.innerText========',innerlength > fontsmaller);
        //根据不同的语言设置不同的元素宽度
        var fontsmaller=30
        if(currLang=='CN'){ fontsmaller=28}
        else if(currLang=='EN'){ fontsmaller=36}
        else { fontsmaller=45}
        if (innerlength > fontsmaller){
            el.style.overflow = 'hidden';
              el.style.textOverflow = 'ellipsis';
              el.style.whiteSpace = 'nowrap';
        /* 第4步:鼠标移入`onmouseenter`事件里需要处理title提示的显示 */ 
          // 创建浮层元素并设置样式
          const kxmTooltipDom = document.createElement('div');
        kxmTooltipDom.style.cssText = `
          display: inline-block;
          max-width: 2rem;
          max-height: 2rem;
          position: absolute;
          top: ${e.clientY + 5}px;
          left: ${e.clientX}px;
          padding: 0.02rem;
          overflow: auto;
          font-size: 0.07rem;
            color: #333;
            background-color: #FFF;
            border-radius: 0.015rem;
            border: 0.005rem solid #333;
            z-index: 19999
          `;
          // 设置id方便寻找
          kxmTooltipDom.setAttribute('id', 'kxm-tooltip');
          // 将浮层插入到body中
          document.body.appendChild(kxmTooltipDom);
          // 浮层中的文字
          document.getElementById('kxm-tooltip').innerHTML = el.innerText;
        }
       // 鼠标移出
          el.onmouseleave = () => {
          // console.log(...arguments);
          /* 第5步:鼠标移出`onmouseleave`需要移出title显示的元素 */ 
            // 找到浮层元素并移出
            const kxmTooltipDom = document.getElementById('kxm-tooltip');
            kxmTooltipDom && document.body.removeChild(kxmTooltipDom);
          }
   		 } 
        // 需要注意:更新完之后需要移除容器,不然body里会多一个span元素内容
        document.body.removeChild(textSpan);
      },
      // 指令与元素解绑时
      unbind () {
      // console.log(...arguments);
      /* 第6步:解绑移除浮层元素 */
        // 找到浮层元素并移除
        const kxmTooltipDom = document.getElementById('kxm-tooltip');
        kxmTooltipDom && document.body.removeChild(kxmTooltipDom);
      }
  }
  
 <el-menu-item v-for="(items, indexs) in item.children"  :key="indexs" :index="items.linkName" v-tooltip >
 	{{ items.linkName }} 
 </el-menu-item>

关于其中offsetWidth、clientWidth、scrollWidth学习记录

关于js中的offsetWidth、clientWidth、scrollWidth等一系列属性及其方法一直都傻傻分不清,这里就来总结一下这些方法的用法和含义。

<script>
    /*
     ****** 元素视图属性
     * offsetWidth 水平方向 width + 左右padding + 左右border-width
     * offsetHeight 垂直方向 height + 上下padding + 上下border-width
     * 
     * clientWidth 水平方向 width + 左右padding
     * clientHeight 垂直方向 height + 上下padding
     * 
     * offsetTop 获取当前元素到 定位父节点 的top方向的距离
     * offsetLeft 获取当前元素到 定位父节点 的left方向的距离
     * 
     * scrollWidth 元素内容真实的宽度,内容不超出盒子高度时为盒子的clientWidth
     * scrollHeight 元素内容真实的高度,内容不超出盒子高度时为盒子的clientHeight
     * 
     ****** 元素视图属性结束
     * 
     ****** Window视图属性(低版本IE浏览器[<IE9]不支持) 【自测包含滚动条,但网络教程都说不包含???】
     * innerWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏) 
     * innerHeight 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏)
     * ***** Window视图属性结束
     * 
     ****** Document文档视图
     * (低版本IE的innerWidth、innerHeight的代替方案)
     * document.documentElement.clientWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏、滚动条)
     * document.documentElement.clientHeight 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏、滚动条)
     * 
     * document.documentElement.offsetHeight 获取整个文档的高度(包含body的margin)
     * document.body.offsetHeight 获取整个文档的高度(不包含body的margin)
     * 
     * document.documentElement.scrollTop 返回文档的滚动top方向的距离(当窗口发生滚动时值改变)
     * document.documentElement.scrollLeft 返回文档的滚动left方向的距离(当窗口发生滚动时值改变)
     ****** Document文档视图结束
     * 
     ****** 元素方法
     * 1. getBoundingClientRect() 获取元素到body
     *  bottom: 元素底边(包括border)到可视区最顶部的距离
     *  left: 元素最左边(不包括border)到可视区最左边的距离
     *  right: 元素最右边(包括border)到可视区最左边的距离
     *  top: 元素顶边(不包括border)到可视区最顶部的距离
     *  height: 元素的offsetHeight
     *  width: 元素的offsetWidth
     *  x: 元素左上角的x坐标 
     *  y: 元素左上角的y坐标 
     * 
     * 2. scrollIntoView() 让元素滚动到可视区
     * 
     * ***** 元素方法结束
     * 
     */
</script>
<think>好的,我现在需要帮用户解决在Vueel-tree组件中添加鼠标悬停提示的问题。首先,用户提到的引用内容里有几个关键点。比如引用[1]中提到了使用renderContent方法来生成节点内容,里面用了title属性来显示提示。不过用户可能发现当文字过长时,原生的title样式不好看,需要自定义悬浮提示。 接下来,引用[2]是关于样式的调整,可能需要覆盖el-tree的默认样式,特别是悬停时的背景色。不过用户的问题是关于文字提示,所以可能这里需要结合CSS来控制提示框的显示位置或者样式。 然后引用[3]和[4]提到了鼠标移入移出的事件处理,比如onShowNameTipsMouseenter方法,这里检测文本是否溢出,决定是否显示提示。用户可能需要类似的方法,在鼠标悬停判断是否需要显示tooltip,并设置对应的内容。 综合这些信息,我需要分步骤来指导用户: 1. 自定义节点内容:使用renderContent函数,在span元素上添加title属性,这是最简单的原生提示方式。不过用户可能想要更美观的提示,比如element-ui的el-tooltip组件。 2. 使用el-tooltip组件:在renderContent中用el-tooltip包裹节点内容,当文字过长时显示。这里需要判断文字是否溢出,可以通过比较scrollWidth和clientWidth,或者offsetWidth来判断。如果溢出,则显示tooltip,否则不显示。 3. 事件处理:在节点元素上绑定mouseenter和mouseleave事件,触发tooltip显示和隐藏。引用[3]中的方法可以借鉴,但需要结合Vue的响应式数据来控制tooltip的状态。 4. CSS样式调整:可能需要调整tooltip的位置或者el-tree节点的样式,比如引用[2]中的方法覆盖默认样式,确保tooltip显示正确。 需要注意,直接使用title属性可能样式不可控,而el-tooltip更灵活。此外,如果节点内容动态变化,可能需要使用refs来获取DOM元素的宽度,或者在updated生命周期中检测溢出情况。 另外,用户可能遇到的挑战是如何在renderContent函数中正确绑定事件和处理Vue实例的上下文。可能需要使用作用域插槽或者函数式组件的方式,或者通过Vue的实例方法访问tooltip的状态。 最后,给出具体的代码示例,结合renderContent、el-tooltip和事件处理,同时说明如何判断文本溢出,并调整CSS样式。这样用户就能一步步实现悬停提示的功能了。</think>在 Vueel-tree 组件中实现鼠标悬停提示文字,可以通过以下步骤实现: ### 一、基础实现方案 1. **自定义节点内容** 使用 `renderContent` 方法重写节点渲染逻辑,添加 `title` 原生属性: ```javascript renderContent(h, { node }) { return ( <span class="custom-tree-node"> <span title={node.label}>{node.label}</span> </span> ) } ``` 该方法会在节点文本溢出时自动显示原生浏览器提示[^1]。 2. **添加 CSS 溢出处理** 在组件样式中添加: ```css .custom-tree-node span { display: inline-block; max-width: 200px; /* 根据列宽调整 */ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } ``` ### 二、进阶优化方案(使用 el-tooltip) ```javascript renderContent(h, { node }) { return ( <el-tooltip placement="top" content={node.label} disabled={!this.isTextOverflow(node)} > <span class="custom-tree-node"> {node.label} </span> </el-tooltip> ) } // 添加文本溢出检测方法 methods: { isTextOverflow(node) { const el = this.$refs.tree.$el.querySelector(`[data-id="${node.id}"] .custom-tree-node`); return el.scrollWidth > el.clientWidth; } } ``` ### 三、动态样式优化 ```css /* 引用 element-ui 的深层次样式 */ :deep(.el-tree-node__content) { &:hover { background-color: #f5f7fa !important; /* 悬停背景色调整[^2] */ } .el-tooltip__trigger { display: block; overflow: hidden; text-overflow: ellipsis; } } ``` ### 四、注意事项 1. 需要给 `el-tree` 添加 `ref="tree"` 属性以便获取 DOM 引用 2. 动态加载数据时需要在 `updated` 生命周期中重新计算溢出状态 3. 对于大量数据建议添加防抖处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值