欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

打造个性化Vue指令:v-tooltip实现文本溢出省略与文字提示(兼容Vue2和Vue3版)

最编程 2024-08-10 11:46:16
...

简介

本文介绍了一种自定义v-tooltip指令的方案,当文本超出时显示省略号且鼠标移入时浮层显示完整文本

效果图

image.png

全局注册

vue3全局注册指令

import { setuptooltipDirective } from "@/directives/tooltip";

setuptooltipDirective(app);

vue2版本只需引入tooltip.js文件即可

使用示例

<div v-tooltip style="width: 100px">
    文本超出测试文本超出测试文本超出测试文本超出测试文本超出测试文本超出测试
</div>

当传入false时指令不生效,用于需要使用变量控制是否超出省略的情况

<div v-tooltip ="false" style="width: 100px">
    文本超出测试文本超出测试文本超出测试文本超出测试文本超出测试文本超出测试
</div>

源码(vue3 + ts)

// directives/tooltip.ts
import type { App, Directive, DirectiveBinding } from "vue";

let tooltipDom: HTMLElement;

const tooltipDirective: Directive = {
  mounted(el: HTMLElement, bindings: DirectiveBinding) {
    bindEvent(el, bindings);
  },
  updated(el: HTMLElement, bindings: DirectiveBinding) {
    bindEvent(el, bindings);
  },
  unmounted() {
    removeTooltip();
  },
};

function bindEvent(el: HTMLElement, bindings: DirectiveBinding) {
  // 先移除上一次绑定的事件
  el.removeEventListener("mouseenter", handleMouseEnter);
  el.removeEventListener("mouseleave", removeTooltip);

  if (bindings.value === false) {
    return;
  }
  // 给当前元素设置超出隐藏
  el.style.overflow = "hidden";
  el.style.textOverflow = "tooltip";
  el.style.whiteSpace = "nowrap";

  // 如果超出,绑定鼠标移入移出事件
  if (el.scrollWidth > el.offsetWidth) {
    el.addEventListener("mouseenter", handleMouseEnter);
    // 鼠标移出 将提示信息移除
    el.addEventListener("mouseleave", removeTooltip);
  }
}

/** 鼠标移入事件 */
function handleMouseEnter(e) {
  if (!tooltipDom) {
    // 创建浮层元素
    tooltipDom = document.createElement("div");
    // 将浮层插入到body中
    document.body.appendChild(tooltipDom);
  }
  const maxWidth = 600;
  let cssText = `
          max-width: ${maxWidth}px;
          overflow: auto;
          position: fixed;
          background: #262627;
          color: #fff;
          border-radius: 4px;
          line-height: 20px;
          padding: 10px;
          display: block;
          font-size: 12px;
          z-index: 99999;
          word-break: break-all;
        `;
  // 根据鼠标移入位置判断浮层位于左侧还是右侧,避免遮挡
  if (window.innerWidth - e.clientX < maxWidth) {
    cssText += `right:${window.innerWidth - e.clientX}px;`;
  } else {
    cssText += `left:${e.clientX + 20}px;`;
  }
  // 根据鼠标移入位置判断浮层位于上方还是下方,避免遮挡
  if (window.innerHeight - e.clientY < 600) {
    cssText += `bottom:${window.innerHeight - e.clientY}px;`;
  } else {
    cssText += `top:${e.clientY}px;`;
  }

  tooltipDom.style.cssText = cssText;
  // 浮层中的文字
  tooltipDom.innerHTML = e.currentTarget.innerText;
}

function removeTooltip() {
  // 隐藏浮层
  if (tooltipDom) {
    tooltipDom.style.display = "none";
  }
}

export function setupTooltipDirective(app: App) {
  app.directive("tooltip", tooltipDirective);
}

源码(vue2 + js)

import Vue from "vue";

let tooltipDom;

Vue.directive("import Vue from "vue";

let tooltipDom;

Vue.directive("import Vue from "vue";

let tooltipDom;

Vue.directive("tooltip", {
  inserted(el, bindings) {
    bindEvent(el, bindings);
  },
  componentUpdated(el, bindings) {
    bindEvent(el, bindings);
  },
  unbind() {
    removeTooltip();
  },
});

function bindEvent(el, bindings) {
  // 先移除上一次绑定的事件
  el.removeEventListener("mouseenter", handleMouseEnter);
  el.removeEventListener("mouseleave", removeTooltip);

  if (bindings.value === false) {
    return;
  }
  // 给当前元素设置超出隐藏
  el.style.overflow = "hidden";
  el.style.textOverflow = "tooltip";
  el.style.whiteSpace = "nowrap";

  // 如果超出,绑定鼠标移入移出事件
  if (el.scrollWidth > el.offsetWidth) {
    el.addEventListener("mouseenter", handleMouseEnter);
    // 鼠标移出 将提示信息移除
    el.addEventListener("mouseleave", removeTooltip);
  }
}

/** 鼠标移入事件 */
function handleMouseEnter(e) {
  if (!tooltipDom) {
    // 创建浮层元素
    tooltipDom = document.createElement("div");
    // 将浮层插入到body中
    document.body.appendChild(tooltipDom);
  }
  const maxWidth = 600;
  let cssText = `
          max-width: ${maxWidth}px;
          overflow: auto;
          position: fixed;
          background: #262627;
          color: #fff;
          border-radius: 4px;
          line-height: 20px;
          padding: 10px;
          display: block;
          font-size: 12px;
          z-index: 99999;
          word-break: break-all;
        `;
  // 根据鼠标移入位置判断浮层位于左侧还是右侧,避免遮挡
  if (window.innerWidth - e.clientX < maxWidth) {
    cssText += `right:${window.innerWidth - e.clientX}px;`;
  } else {
    cssText += `left:${e.clientX + 20}px;`;
  }
  // 根据鼠标移入位置判断浮层位于上方还是下方,避免遮挡
  if (window.innerHeight - e.clientY < 600) {
    cssText += `bottom:${window.innerHeight - e.clientY}px;`;
  } else {
    cssText += `top:${e.clientY}px;`;
  }

  tooltipDom.style.cssText = cssText;
  // 浮层中的文字
  tooltipDom.innerHTML = e.currentTarget.innerText;
}

function removeTooltip() {
  // 隐藏浮层
  if (tooltipDom) {
    tooltipDom.style.display = "none";
  }
}", {
  inserted(el, bindings) {
    bindEvent(el, bindings);
  },
  componentUpdated(el, bindings) {
    bindEvent(el, bindings);
  },
  unbind() {
    removeTooltip();
  },
});

function bindEvent(el, bindings) {
  // 先移除上一次绑定的事件
  el.removeEventListener("mouseenter", handleMouseEnter);
  el.removeEventListener("mouseleave", removeTooltip);

  if (bindings.value === false) {
    return;
  }
  // 给当前元素设置超出隐藏
  el.style.overflow = "hidden";
  el.style.textOverflow = "tooltip";
  el.style.whiteSpace = "nowrap";

  // 如果超出,绑定鼠标移入移出事件
  if (el.scrollWidth > el.offsetWidth) {
    el.addEventListener("mouseenter", handleMouseEnter);
    // 鼠标移出 将提示信息移除
    el.addEventListener("mouseleave", removeTooltip);
  }
}

/** 鼠标移入事件 */
function handleMouseEnter(e) {
  if (!tooltipDom) {
    // 创建浮层元素
    tooltipDom = document.createElement("div");
    // 将浮层插入到body中
    document.body.appendChild(tooltipDom);
  }
  const maxWidth = 600;
  let cssText = `
          max-width: ${maxWidth}px;
          overflow: auto;
          position: fixed;
          background: #262627;
          color: #fff;
          border-radius: 4px;
          line-height: 20px;
          padding: 10px;
          display: block;
          font-size: 12px;
          z-index: 99999;
          word-break: break-all;
        `;
  // 根据鼠标移入位置判断浮层位于左侧还是右侧,避免遮挡
  if (window.innerWidth - e.clientX < maxWidth) {
    cssText += `right:${window.innerWidth - e.clientX}px;`;
  } else {
    cssText += `left:${e.clientX + 20}px;`;
  }
  // 根据鼠标移入位置判断浮层位于上方还是下方,避免遮挡
  if (window.innerHeight - e.clientY < 600) {
    cssText += `bottom:${window.innerHeight - e.clientY}px;`;
  } else {
    cssText += `top:${e.clientY}px;`;
  }

  tooltipDom.style.cssText = cssText;
  // 浮层中的文字
  tooltipDom.innerHTML = e.currentTarget.innerText;
}

function removeTooltip() {
  // 隐藏浮层
  if (tooltipDom) {
    tooltipDom.style.display = "none";
  }
}", {
  inserted(el, bindings) {
    bindEvent(el, bindings);
  },
  componentUpdated(el, bindings) {
    bindEvent(el, bindings);
  },
  unbind() {
    removeTooltip();
  },
});

function bindEvent(el, bindings) {
  // 先移除上一次绑定的事件
  el.removeEventListener("mouseenter", handleMouseEnter);
  el.removeEventListener("mouseleave", removeTooltip);

  if (bindings.value === false) {
    return;
  }
  // 给当前元素设置超出隐藏
  el.style.overflow = "hidden";
  el.style.textOverflow = "tooltip";
  el.style.whiteSpace = "nowrap";

  // 如果超出,绑定鼠标移入移出事件
  if (el.scrollWidth > el.offsetWidth) {
    el.addEventListener("mouseenter", handleMouseEnter);
    // 鼠标移出 将提示信息移除
    el.addEventListener("mouseleave", removeTooltip);
  }
}

/** 鼠标移入事件 */
function handleMouseEnter(e) {
  if (!tooltipDom) {
    // 创建浮层元素
    tooltipDom = document.createElement("div");
    // 将浮层插入到body中
    document.body.appendChild(tooltipDom);
  }
  const maxWidth = 600;
  let cssText = `
          max-width: ${maxWidth}px;
          overflow: auto;
          position: fixed;
          background: #262627;
          color: #fff;
          border-radius: 4px;
          line-height: 20px;
          padding: 10px;
          display: block;
          font-size: 12px;
          z-index: 99999;
          word-break: break-all;
        `;
  // 根据鼠标移入位置判断浮层位于左侧还是右侧,避免遮挡
  if (window.innerWidth - e.clientX < maxWidth) {
    cssText += `right:${window.innerWidth - e.clientX}px;`;
  } else {
    cssText += `left:${e.clientX + 20}px;`;
  }
  // 根据鼠标移入位置判断浮层位于上方还是下方,避免遮挡
  if (window.innerHeight - e.clientY < 600) {
    cssText += `bottom:${window.innerHeight - e.clientY}px;`;
  } else {
    cssText += `top:${e.clientY}px;`;
  }

  tooltipDom.style.cssText = cssText;
  // 浮层中的文字
  tooltipDom.innerHTML = e.currentTarget.innerText;
}

function removeTooltip() {
  // 隐藏浮层
  if (tooltipDom) {
    tooltipDom.style.display = "none";
  }
}