参考链接:# vue3通过ElementPlus的tooltip组件实现自定义指令文字提示
前言
- 实际项目中我们往往都希望整个项目的 tooltip 样式应该是保持一致的
- 然而现实是管理上很难让所有开发人员做到 tooltip 样式一致(特别是没有设计的情况下),有的开发人员不愿意问,也懒得去参考其他地方,或者项目里已经乱了,比如有的地方tooltip是白色的有的地方是黑色的,开发人员也懒得问的情况下,就继续随便搞了,这很常见,也不能怪谁
- 所以呢,咱们就需要从架构层去考虑和控制避免这种不统一的问题
- 那在 vue3 项目中,我想到的最直接的方法就是通过【自定义指令】去实现,一来是方便统一管理整个项目的 tooltip,二来呢所有项目里也不需要繁琐得去写 el-tooltip 了,一个指令就能搞定,轻松解决这种不起眼又挺烦人的问题
效果展示
自定义指令代码在此!!!
import { DirectiveBinding } from 'vue'
import { ElTooltip } from 'element-plus'
/**
* 判断文本是否溢出
*/
function isTextOverflowing(element) {
const style = window.getComputedStyle(element)
const range = document.createRange()
range.selectNodeContents(element)
const contentWidth = range.getBoundingClientRect().width
const containerWidth = parseFloat(style.width)
return contentWidth > containerWidth
}
/**
* 创建tooltip,这里采用element-plus的tooltip组件
* 使用案例:
* <span v-text-tootip:auto>xxxxxxx</span> tooltip 自定判断文本是否溢出,溢出了鼠标悬浮才会展示tooltip
* <span v-text-tootip>xxxxxxx</span> tooltip 直接悬浮展示tooltip
* @param el
* @param binding
*/
const createTooltip = (el: any, binding: DirectiveBinding) => {
const arg = binding.arg
const isShow = arg === 'auto' ? isTextOverflowing(el) : true // binding.value || true
// 创建组件,显示tooltip
if (isShow) {
// 判断是否有根元素,存在,则移除
const elRoot = document.querySelector('#_tooltip_root')
if (elRoot) {
elRoot.remove()
}
// 初始化 根元素
el._tiproot = null
el._tipapp = null
const id = '_tooltip_root'
const _tiproot = document.createElement('div')
_tiproot.id = id
// 通过createApp 创建实例组件
const _tipapp = createApp(ElTooltip, {
trigger: 'hover',
virtualRef: el,
rawContent: true,
placement: 'top',
virtualTriggering: true,
content: el.innerHTML
})
el._tiproot = _tiproot
el._tipapp = _tipapp
// body添加根元素
document.body.appendChild(_tiproot)
// 将新组件挂载到根元素
if (_tipapp && _tiproot) {
el._tipapp.mount('#' + id)
}
}
}
/**
* 文本溢出则显示省略号并悬浮鼠标展示tooltip
*/
export const textTootip = (el, binding: DirectiveBinding) => {
// 文本溢出则展示省略号
el.style.whiteSpace = 'nowrap'
el.style.overflow = 'hidden'
el.style.textOverflow = 'ellipsis'
// 创建tooltip
createTooltip(el, binding)
}
注册全局指令
import textTootip from './textTootip'
app.directive('textTootip', textTootip)