背景
项目中使用Element中的tooltip可以快速实现hover功能;而该组件默认触发机制是鼠标移动到对应的元素上时就显示tooltip;但是业务需要子级文本超出父级才显示,所以该行为往往不符合业务需求,这时候就涉及到元素的动态计算,而此时使用tooltip组件反而使模块中出现很多重复代码。
封装Tooltip指令
import Vue from 'vue'
import Popper from 'element-ui/src/utils/popper'
import PopupManager from 'element-ui/src/utils/popup/popup-manager'
class Tooltip {
constructor() {
this.options = {
offset: 0,
arrowOffset: 0,
placement: 'top',
boundariesPadding: 10,
gpuAcceleration: false,
}
this.tooltip = new Vue({
data() {
return {
content: '',
showPopper: false,
disabled: false,
effect: 'dark'
}
},
render() {
return <div v-show={ !this.disabled && this.showPopper } class={ ['el-tooltip__popper', "is-"+this.effect, this.popperClass] }>
{ this.content }<div x-arrow class="popper__arrow"></div>
</div>
}
}).$mount()
document.body.appendChild(this.tooltip.$el)
}
handleEnter(props, el) {
let content = props.value.content
if (typeof content === 'function' && !(content = content())) return
el = el.target || el
if (props.modifiers.overflow) {
const style = getComputedStyle(el)
// const range = document.createRange()
// range.setStart(el, 0)
// range.setEnd(el, el.childNodes.length)
const rangeDom = el.getBoundingClientRect()
let width = parseInt(style.paddingLeft) + parseInt(style.paddingRight) + Math.round(rangeDom.width)
if (width <= el.parentNode.offsetWidth) return
}
this.tooltip.showPopper = true
this.tooltip.content = content
this.tooltip.$nextTick(() => {
const popperJs = new Popper(el, this.tooltip.$el, Object.assign(this.options, props.value.options || {}))
popperJs._popper.style.zIndex = PopupManager.nextZIndex()
})
}
handleLeave() {
this.tooltip.showPopper = false
}
bind(el, binding) {
if (!binding.value.content) return
el.addEventListener('mouseenter', binding.def.handleEnter.bind(binding.def, binding))
el.addEventListener('mouseleave', binding.def.handleLeave.bind(binding.def))
}
unbind(el, binding) {
if (!binding.value.content) return
el.removeEventListener('mouseenter', binding.def.handleEnter)
el.removeEventListener('mouseenter', binding.def.handleLeave)
}
}
Vue.directive('popper', new Tooltip())
如何使用
注意:使用当前指令并且修饰符为overflow的元素,不能有同级元素
使用方法如下
<span v-popper.overflow="{ content: 'Top center', options: { placement: 'top-start' } }">Top center</span>
该指令有两个修饰符,分别为overflow、hover(默认值);另外有两个参数content、options; 当content内容是动态数据时,此时content是个函数。