1. 产品需求
-
如果超出宽度则
显示省略号
并且hover
tooltip提示
-
如果没有超出即没有展示省略号,则
不要tooltip提示
其实,产品的核心要求就是去掉不显示省略号的tooltip提示,因为它已经展示全了,提示就多余了
2. 分析
因为我这个项目很大,不算遍历的,可能全局有100多个个vue文件有el-tootip的文案提示,总计可能几百处需要修改的地方,所以想到了下面几个方法
-
Vue.prototype上面挂载一个全局的方法,试了下不好实现,很多东西获取不到,又涉及到异步获取不到dom的问题(执行的时候页面没有加载完)。
排除
-
Vue全局过滤器,但是Vue3好像没这个东西了,所以
排除
-
自定义指令
。看一下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
:
- 全局新建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元素,即真实的宽度
},
});
};
- 在main.js中调用注册
import Vue from 'vue';
import initDirectives from '@/utils/directives';
initDirectives(Vue); // Vue全局自定义指令
最后,在组件中使用自定义指令真的是舒服呀
版权声明:本文为s18438610353原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。