Vue及ElementUI中自定义指令实现判断文本内容超出显示省略号和el-tooltip提示,不超出则禁用el-tooltip

1. 产品需求

  1. 如果超出宽度则显示省略号并且hover tooltip提示
    在这里插入图片描述
  2. 如果没有超出即没有展示省略号,则不要tooltip提示

在这里插入图片描述

其实,产品的核心要求就是去掉不显示省略号的tooltip提示,因为它已经展示全了,提示就多余了

2. 分析

因为我这个项目很大,不算遍历的,可能全局有100多个个vue文件有el-tootip的文案提示,总计可能几百处需要修改的地方,所以想到了下面几个方法

  1. Vue.prototype上面挂载一个全局的方法,试了下不好实现,很多东西获取不到,又涉及到异步获取不到dom的问题(执行的时候页面没有加载完)。排除
  2. Vue全局过滤器,但是Vue3好像没这个东西了,所以排除
  3. 自定义指令。看一下2.0官网对它的简介描述

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

因为我目前能想到的判断是否超出宽度的方法只有通过操作DOM判断,所以再合适不过了。

3.代码实现

template模板

<el-tooltip
	content="" v-showtip
	placement="top-start">
	<span
		class="value copy_btn">
		<span class="ellipse-text">{
   
   { item.hostname || '--' }}</span>
	</span>
</el-tooltip>

部分CSS

.value {
    
    
   flex: 1; // 核心 上级元素flex布局,flex1后可获取真实宽度判断
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
 }
 .ellipse-text{
    
    } // 目前什么内容都没有,方便标识而已

JS全局注册Vue自定义指令v-showtip:

  1. 全局新建directives.js
const compareWidth = (el) => {
    
    
  // 如果没有超出宽度,即子<父 则移除tooltip
  if (el.querySelector('.ellipse-text') && el.querySelector('.ellipse-text').offsetWidth < el.offsetWidth) {
    
    
    const copyEl = el.parentNode; // 获取到目标节点的父节点
    const copySpan = el.querySelector('.ellipse-text'); // 获取到目标节点的子节点,即纯粹的span标签文案
    el.parentNode.removeChild(el); // 移除带有el-tooltip组件的节点
    copyEl.appendChild(copySpan); // 将纯粹的span标签文案整体追加到目标节点的父节点
  }
};
export default (Vue) => {
    
    
  // 注册一个全局自定义指令 `showtip`
  Vue.directive('showtip', {
    
    
  	// 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    bind: (el, binding) => {
    
    
    // bind的时候无法获取到已经带有ajax数据的DOM元素,宽度为0
    },
    // 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    inserted: (el) => {
    
    
      compareWidth(el); // 可以获取到ajax数据的DOM元素,即真实的宽度
    },
    // 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
    update: (el) => {
    
    
      compareWidth(el); // 可以获取到ajax数据的DOM元素,即真实的宽度
    },
  });
};

  1. 在main.js中调用注册
import Vue from 'vue';
import initDirectives from '@/utils/directives';

initDirectives(Vue); // Vue全局自定义指令

最后,在组件中使用自定义指令真的是舒服呀

猜你喜欢

转载自blog.csdn.net/s18438610353/article/details/125226506