网络日志

自定义vue指令-文本超出省略以及文字提示:v-ellipsis(vue2 + vue3版本)

简介

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

效果图

全局注册

vue3全局注册指令

import { setupEllipsisDirective } from "@/directives/ellipsis";

setupEllipsisDirective(app);

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

使用示例

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

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

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

源码(vue3 + ts)

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

let tooltipDom: HTMLElement;

const ellipsisDirective: 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 = "ellipsis";
  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 setupEllipsisDirective(app: App) {
  app.directive("ellipsis", ellipsisDirective);
}

源码(vue2 + js)

import Vue from "vue";

let tooltipDom;

Vue.directive("ellipsis", {
  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 = "ellipsis";
  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";
  }
}