使用vue3自定义指令实现Tooltip

效果预览:

实现代码:

directive.js

javascript 复制代码
import { nextTick } from "vue"

function elFover(e) {

	// e.el.classList.add('hover')

	let res = e.el.getBoundingClientRect()
	// console.log(res)

	let dom_tooltip = document.querySelector('.c-tooltip')
	
	if(dom_tooltip) {
		dom_tooltip.style.display = 'block'
		dom_tooltip.querySelector('.ivu-tooltip-inner').innerText = e.val
	
	} else {
		let _div = document.createElement('div')
		_div.innerHTML = `<div class="c-tooltip ivu-tooltip-popper ivu-tooltip-dark ivu-tooltip-transfer" style="z-index: 1099; position: fixed; will-change: top, left; top: 0px; left: 0px;" x-placement="top">
		<div class="ivu-tooltip-content">
			<div class="ivu-tooltip-arrow"></div>
			<div class="ivu-tooltip-inner">${e.val}</div>
		</div>
	</div>`
		document.body.appendChild(_div)

		
	}

	nextTick(() => {
		!dom_tooltip && (dom_tooltip = document.querySelector('.c-tooltip'))
		let _res = dom_tooltip.getBoundingClientRect()

		if(res.top < _res.height) {
			dom_tooltip.style.top = res.bottom +'px'
			dom_tooltip.setAttribute('x-placement', 'bottom')
		} else {
			dom_tooltip.style.top = (res.top - _res.height) +'px'
			dom_tooltip.setAttribute('x-placement', 'top')
		}

		if(res.left < (_res.width - res.width)/2) {
			dom_tooltip.style.left = 0 +'px'
		} else if(window.innerWidth - res.right < (_res.width - res.width)/2) {
			dom_tooltip.style.left = (window.innerWidth - _res.width) +'px'
		} else {
			dom_tooltip.style.left = (res.left + (res.width - _res.width)/2) +'px'
		}

		
	})
	
}

function elLeave() {
	let dom_tooltip = document.querySelector('.c-tooltip')
	
	if(dom_tooltip) {
		dom_tooltip.style.display = 'none'
	}
}

let fb = undefined

export const vFocus = {
	mounted: (el, binding) => {
		fb = elFover.bind(this, {
			el: el,
			val: binding.value
		})
		el.addEventListener('mouseenter', fb)
		el.addEventListener('mouseleave', elLeave)
	},
	// 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {
		el.removeEventListener('mouseenter', fb)
		el.removeEventListener('mouseleave', elLeave)
	},
}

main.ts

TypeScript 复制代码
import { vFocus } from '@/utils/directive.js'
import { createApp } from 'vue'

const app = createApp(App)
app.directive('focus', vFocus)

组件里使用

TypeScript 复制代码
<i class="md-more" v-focus="'更多'"></i>
相关推荐
excel7 小时前
ES6 中函数的双重调用方式:fn() 与 fn\...``
前端
可乐爱宅着7 小时前
全栈框架next.js入手指南
前端·next.js
你的人类朋友8 小时前
什么是API签名?
前端·后端·安全
会豪10 小时前
Electron-Vite (一)快速构建桌面应用
前端
中微子10 小时前
React 执行阶段与渲染机制详解(基于 React 18+ 官方文档)
前端
唐某人丶10 小时前
教你如何用 JS 实现 Agent 系统(2)—— 开发 ReAct 版本的“深度搜索”
前端·人工智能·aigc
中微子10 小时前
深入剖析 useState产生的 setState的完整执行流程
前端
遂心_11 小时前
JavaScript 函数参数传递机制:一道经典面试题解析
前端·javascript
Gracemark11 小时前
高德地图-地图选择经纬度问题【使用输入提示-使用Autocomplete进行联想输入】(复盘)
vue.js
小徐_233311 小时前
uni-app vue3 也能使用 Echarts?Wot Starter 是这样做的!
前端·uni-app·echarts