Custom instructions in Vue and ElementUI implement judgment that the text content exceeds the display ellipsis and el-tooltip prompt, and disables el-tooltip if it does not exceed the limit.

1. Product requirements

  1. if it exceeds the width then 显示省略号and hovertooltip提示
    Insert image description here
  2. If there is no excess, that is, no ellipsis is displayed, then不要tooltip提示

Insert image description here

In fact, the core requirement of the product is to remove the tooltip prompt that does not display the ellipsis, because it has been fully displayed, and the prompt is redundant.

2. Analysis

Because my project is very large, not counting traversal, there may be more than 100 vue files with el-tootip copywriting prompts, and there may be hundreds of places that need to be modified, so I thought of the following methods.

  1. There is a global method mounted on Vue.prototype, but it is difficult to implement after trying it. Many things cannot be obtained, and it also involves the problem of not being able to obtain the DOM asynchronously (the page is not loaded during execution). exclude
  2. Vue global filter, but Vue3 seems to have no such thing, so it is excluded.
  3. 自定义指令. Take a look at the brief description of it on the 2.0 official website

In addition to the default built-in directives (v-model and v-show) of the core functionality, Vue also allows the registration of custom directives. Note that in Vue2.0, the main form of code reuse and abstraction is components. However, in some cases, you still need to perform low-level operations on ordinary DOM elements, in which case custom directives are used.

Because the only way I can think of to determine whether the width is exceeded is through 操作DOM判断, it couldn't be more appropriate.

3. Code implementation

templatetemplate

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

Partial CSS

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

JS global registration of Vue custom instructionsv-showtip :

  1. Create new directives.js globally
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. Call registration in main.js
import Vue from 'vue';
import initDirectives from '@/utils/directives';

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

Finally, it’s really comfortable to use custom directives in components.

Guess you like

Origin blog.csdn.net/s18438610353/article/details/125226506